Attenzione! Parse ha deciso di chiudere i battenti a Gennaio 2017. Ho, per tanto, deciso di non trattare più Parse come sistema di supporto. Da ora in avanti utilizzeremo Firebase. Clicca qui per aggiornarti

Prima di implementare qualsiasi sistema di login online, che sia Facebook, Parse, Twitter o altri, qual’è il motivo che ti spinge un programmatore a forzare l’utente a doversi autenticare?

Cioè mi spiego meglio! Perché – biipp biippp – vuoi i miei maledettissimi dati personali?

Questa non è un’esercitazione!

C’è una netta correlazione tra le recensioni positive di un’applicazione e la mancanza di un sistema d’autenticazione. Le app senza il login-form sono più soggette a critiche positive.

I motivi possono essere tanti. Se fino a qualche hanno fa andava di moda sventolare, a destra e a sinistra, la tutela della privacy e quindi un’app con sistema di login era ben vista, oggi, l’utente medio, non fa più caso a cosa sia la privacy e preferisce vedere il sistema di autenticazione solo come un impedimento all’utilizzo dell’applicazione. Per impedimento si intende: la necessità di dover aspettare email di conferme, errori di battitura, connessione non disponibile, bombe, aerei e allah akbar vari.

Non c’è bisogno che te lo dica io, avrai sicuramente provato sulla tua pelle come cala drasticamente l’interesse, in un’applicazione, quando la prima cosa che ti trovi di fronte, alla prima apertura, è una bellissima pagina di log-in.

Più utenti che perdono l’interesse = meno utenti che utilizzano l’app.

Meno utenti che utilizzano l’app significa, tradotto nella lingua degli elfi di Eryn Galen, meno fonti di guadagno.

Ovviamente non voglio dire che nessuna applicazione dovrebbe avere un sistema di login, a tutto c’è un perché, volevo solo farti riflettere sulle scelte di certe implementazioni rispetto ad altre.

Ecco perché in questo tutorial, oltre a creare app con login online a database Parse in swift, voglio parlarti dei 3 motivi principali che spingono un programmatore a scegliere di implementare un sistema di autenticazione.

Il tutorial è stato aggiornato per supportare il linguaggio Swift 2.0 o successivi ed Xcode 7 o successivi. 

3 motivi per creare un sistema di login online con parse e swift

3 Motivi per creare un sistema di login online

Ecco i motivi che dovrebbero spingerti ad utilizzare un sistema di autenticazione:

#1 Creare un’app social based

Forse il motivo più scontato. Chi vuole far autenticare i propri utilizzatori lo fa con lo scopo di mettere in relazioni i dati dell’utente con quelli degli altri utilizzatori.

Non mi riferisco solo ai tipi di comunicazione a cui sei abituato con facebook e twitter, quindi condivisione di contenuti, bensì ad un sistema che sfrutta la connettività per poter confrontare gli utenti fra loro.

Mi spiego meglio. Una applicazione che mi sento in dovere di citarti è: Peak, annoverata tra le migliori app del 2014, ha sfruttato l’autenticazione degli utenti per poter creare un sistema, davvero particolare, che permette di confrontare il proprio punteggio mentale con il resto dei giocatori di tutto il mondo. Peak, oltre ad invogliarti ad allenare la mente con i suoi giochi, ti spinge indirettamente a far di meglio mettendoti a confronto con le performance degli altri giocatori.

Non male aggiungerei! Perché sei fai un paio di conti, e stime, su quanti sono gli utilizzatori dell’app, puoi ipotizzare quanto hanno guadagnato e quanto guadagnano con questa scelta di progettazione.

#2 Creare App cloud based

Molte applicazioni adottano l’autenticazione per poter conservare le informazioni che, un utente specifico, genera per poterle poi allocare successivamente in un altro dispositivo del medesimo utente.

Molti programmatori non fanno uso della potenza del cloudKit Apple perché non è usufruibile da altre piattaforme non iOS-OSX. Ecco perché io ho scelto uno dei suoi più letali concorrenti: Parse Online (utilizzabile da qualsiasi dispositivo, iOS-Android-Winzoz).

Immagina un’applicazione che conservi i dati di una lista della spesa (lo ammetto, sono un po’ fissato con questa lista della spesa!). Come fai a portare i dati di un utente in un’altra applicazione? Semplice, mi dirai! Basta associare i dati, di un’applicazione ad un utente univoco, ed ecco che quella lista sarà finalmente accessibile da qualsiasi applicazione che utilizza lo stesso database di riferimento (Sempre e il solo amato Parse).

#3 Creare una mail list

Questo è un argomento complesso, che richiederebbe uno studio ben approfondito e che ti potrebbe permettere di guadagnare e fidelizzare gli utenti.

Purtroppo in Italia ancora manca quel way of thinking tipicamente americano che li spinge sempre a vedere le cose da un punto di vista pragmatico, materiale e imprenditoriale.

Ok, vado dritto al sodo perché questo argomento, come la programmazione ad oggetti, è uno di quelli che mi ha preso fino in fondo e potrei parlarne all’infinito…

Conservare le email ti permette di creare un canale di comunicazione alternativa con gli utenti.

Questa logica sei abituato a vederla applicata ai siti web. Non mi riferisco alle email di notifica, stile facebook, bensì ad un tipo di comunicazione diretta con un gruppo di persone che sono interessate ad un tipo di servizio che offri.

Sto parlando delle newsletter informative. Ad esempio quella del mio blog, ti puoi registrare dalla barra in alto, ti permette di restare in contatto con me anche se non visiti il sito. Ovvero io so che ti sei registrato alla mia mail list perché sei un appassionato di sviluppo applicazioni e tu sai che riceverai, da me, delle newsletter che ti avvisano quando sono usciti nuovi contenuti o offerte particolari (quest’ultima ancora non l’ho applicata perché non ho niente in vendita).

In questo modo, se non visiti il sito da 3/4 mesi, ho un canale che mi permette di arrivare direttamente a te.

Ecco come hai creato un circolo vizioso. Tu non mi visiti perché ti sei dimenticato di me, per i tuoi motivi o perché hai già letto tutti gli articoli, io ti invio una email avvisandoti dei nuovi contenuti e tu ritorni a visualizzare i nuovi contenuti. Ovviamente, fin quando non ti cancelli dalla sottoscrizione alla mail list.

Perché non applicare il sistema delle mail list anche alle applicazioni?

Se hai creato un sistema di login, che rientra nel punto 1 e 2, non vedo perché non dovresti usufruire delle loro email per tenerli aggiornati o addirittura fare delle offerte ad hoc solo per loro (quest’ultimo punto, la vendita di prodotti tramite email, andrebbe attenzionato con cura. Se ti interessa contattami tramite email).

Questa scelta, in più, ti permette di avvisare la platea degli utenti, registrati alle tue app, di nuove applicazioni da te sviluppate. Quante volte ti è capitato di non sapere che uno sviluppatore ha creato nuove applicazioni?

Cosa imparerai da questo tutorial e perché utilizzare Parse Online

Nel tutorial introduttivo a Parse, ti ho insegnato a creare un’applicazione con capacità di storage online, so di non essere stato esaustivo per quanto riguarda certi aspetti di sincronizzazione, cercherò di colmare alcune lacune sia in questo tutorial che nei successivi. Anyway, in questo tutorial voglio concentrarmi su:

  • Rappresentazione di un’application istance tramite User Class
  • Login, Signup e current user con Parse e Bolts Framework

Perché Parse Online

Parse, come già ribadito, non è solo un servizio di archiviazione dati, infatti permette di creare sistemi di autenticazione protetti (tra i più efficienti in circolazione), sia personali che tramite sincronizzazione account Facebook e Twitter, invio di notifiche push online e cosa più importante, Parse, è perfettamente adattabile a tutti i sistemi operativi portatili e desktop in circolazione.

Quindi se stai creando delle applicazioni multipiattaforma, o no, e vuoi un sistema sicuro, gratuito e personalizzabile, Parse è quello che fa per te.

Il progetto iniziale e le interfacce di login e signup

Voglio farti entrare direttamente sul ring. Ho creato il progetto iniziale che ti invito a scaricare da qui:

[wpdm_package id=’4295′]

 

Il progetto prevede 3 ViewController, ognuno delegato a svolgere una sola funzione:

  • LoginViewController – Il punto di partenza dell’applicazione, permette all’utente di, loggare con il proprio account e, qualora non avesse un account, di registrarne un nuovo.
  • SignUpViewController – la pagina in cui l’utente può registrare un nuovo account
  • MainViewController – il cuore dell’applicazione, la pagina in cui arriva l’utente una volta che ha loggato con il proprio username e password

storyboard applicazione login parse online swift

Questo tipo di storyboard lo ritrovi praticamente in qualsiasi tipo di applicazione che utilizza un sistema di autenticazione online. Nota anche come dalla signUpViewController non parte nessun segue verso la MainViewController. Il motivo è che non voglio far passare qualsiasi utente alla main se non prima ha autenticato almeno una volta il suo account (ci possono essere i furbetti che creano un account ad minchiam per saltare i passaggi).

Il bottone “Signup Now!” della LoginView non ha nessuna Action associata perché performa un segue verso il controller di riferimento. Dall’altro lato, il “Signup Now!” della SignUpView ha una action che servirà a registrare l’utente ed in più è collegato ad un Exit Event (il returnToLoginView che si trova nella LoginView) che permetterà di ritornare indietro alla LoginView una volta che l’utente avrà registrato il suo account.

Il progetto che ti ho fornito è perfettamente adattato a qualsiasi tipo di layout portrait (lo è anche per la landscape ma non mi piace molto il tipo di visualizzazione), che sia iphone 6S Plus o ipad air.

Che stregoneria è mai questa? Si chiama Auto Layout e Size class. Ne ho parlato in diversi tutorial:

Se invece sei interessato a studiare nel dettaglio questi processi e la realizzazione di applicazioni iOS dalle basi, ti consiglio di seguire i miei corsi che puoi trovare qui.

Correggere gli errori, gli import dei framework Bolts e Parse

Per far funzionare parse (dato che nel codice ho già scritto gli import e il set dell’application) devi importare tutti i framework utili al suo funzionamento. L’ho già spiegato nel precedente tutorial (si devi andartelo a leggere!), alla fine dovresti avere i seguenti framework importati:

Dipendenze framework Parse

L’ultimo passaggio è quello di creare la connessione con l’application creata su Parse. Apri il file AppDelegate.swift e, nel metodo didFinishLaunchingWithOptions, aggiungi:

Parse.setApplicationId("TuaApplicationID", clientKey: "TuaClientKey")

Se non stai lavorando con il mio progetto, ricordati di aggiungere l’import al framework Parse. Dove prendere le chiavi della tua applicazione te l’ho spiegato nel tutorial precedente.

La classe PFUser, come funziona il login online tramite Parse

Dal tutorial introduttivo dovresti aver appreso che i dati, in Parse, vengono salvati mediante l’utilizzo di un oggetto della classe PFObject. Questa classe però, hanno ben pensato gli sviluppatori, se utilizzata con lo scopo di immagazzinare dati sensibili come email e password, può risultare poco sicura (c’è da dire che, in ogni modo, tutti i dati vengono cryptati prima di essere spediti).

Per rappresentare istanze particolari, quale quella che rappresenta l’utente, puoi utilizzare una subclass della classe PFObject. Nel caso di una Class per la rappresentazione di un Utente, la classe di riferimento si chiama, guarda caso, PFUser.

La classe PFUser nasce con lo scopo di essere utilizzata per l’autenticazione sicura degli utenti. Di default è già prevista di 3 attributi: username, password e email.

Username e Password sono attributi obbligatori per qualsiasi utente, questo vuol dire che l’autenticazione avverrà mediante essi, mentre l’email non è necessaria al fine della registrazione di un utente.

Ovviamente la classe PFUser ha gli stessi metodi e capacità della classe PFObject dato che è una sua subclass (quindi puoi aggiungere nuovi attributi o utilizzare i metodi della classe padre).

Registrare un nuovo utente su Parse

Per loggarti hai bisogno di creare un utente. Apri il SignUpViewController.swift e nel metodo signUp_clicked, aggiungi il seguente codice:

    @IBAction func signUp_clicked(sender: UIButton) {
        // creo un nuovo utente istanziando un oggetto della classe PFUser
        let newUser = PFUser()
        
        // assegno alle proprietà di default, dell'oggetto newUser, i valori contenuti nei rispettivi field
        newUser.username = field_username.text
        newUser.password = field_password.text
        newUser.email = field_email.text
        
        // dato che si comporta com un PFObject qualsiasi, avresti potuto aggiungere nuove proprietà
        //   con la sintassi standard:
        
        // newUser["Nome Completo"] = "Giuseppe Sapienza"
        // newUser["Età"] = 21
        
        
        //  registro l'utente utilizzando il metodo asincrono signUpInBackgroundWithBlock
        //  il metodo accetta una closure di tipo (result: Bool, error: NSError) -> ()
        //  se la closure non genera errore "if error == nil" allora l'utente è stato
        //  correttamente registrato e quindi aziona un segue che ritorna l'app alla LoginView
        //  altrimenti c'è stato un problema!
        
        newUser.signUpInBackgroundWithBlock { (result, error) -> Void in
            if error == nil {
                print("[PARSE] SignUp successfull")
                self.performSegueWithIdentifier("returnToLoginSegue", sender: self)
            } else {
                let error_message = error!.description
                print("[ERROR] SignUp with error: \(error_message)")
            }
        }
    }

Voglio spendere 2 parole esatte per il metodo utilizzato per registrare l’utente.

Intanto è palese come senza la conoscenza di un po’ del linguaggio Swift ed in particolare la programmazione ad oggetti e le closure expression è quasi impossibile capire cosa ci sia scritto in quel codice, quindi se non lo hai ancora fatto, segui il corso gratuito di programmazione Swift.

La funzione signUpInBackgroundWithBlock è di tipo asincrono, non voglio entrare nel merito (ci ritornerò in un tutorial a parte), questo vuol dire che lei, una volta che verrà eseguita, dato che richiederà la connessione ad internet e al server parse, non bloccherà l’applicazione per completare tutte le sue operazioni.

Nel codice non ho inserito il controllo sull’eguaglianza dei vari textField per rendere più snello il codice. Puoi implementarlo da solo aggiungendo le varie istruzioni guard:

        // eseguo dei controlli sui textField
        // da inserire a monte del codice della IBAction
        guard let nome = self.field_username.text else {
            return
        }
        
        guard let password = self.field_password.text else {
            return
        }
        
        guard let re_password = self.field_rePassword.text else {
            return
        }
        
        guard let email = self.field_email.text else {
            return
        }
        
        guard password == re_password else {
            return
        }
// il resto della funzione di registrazione

Se hai dei problemi, in fondo al tutorial, trovi il codice completo.

Prova a registrare un nuovo account, se tutto è andato per il verso giusto, in console dovresti vedere il messaggio di avvenuta registrazione:

test signup with parse and swift

Alcuni casi di errore standard:

  • Email con forma non standard. Se provi ad inserire una email senza chiocciola o estensione, oppure se il tipo di email non fa parte di una lista di domini sicuri, il signup fallirà generando un errore.
  • Password con caratteri non validi.
  • Username già utilizzato.
  • Username con caratteri non validi.

La dashboard di Parse

Anche in questo caso, come nel tutorial introduttivo, ti ho fatto creare una Classe Parse a partire dal codice dell’applicazione. Il processo inverso è ovviamente possibile. Però come ti avevo già detto, in questo modo crei solo ed esclusivamente quello che effettivamente ti serve per la tua applicazione.

Parse, una volta che riceverà una richiesta dalla tua applicazione, controllerà se esiste la classe di riferimento. Se c’è la aggiorna, se non c’è la aggiunge e provvede a creare gli oggetti o a modificarli.

Questo è il processo che hai appena utilizzato, infatti se vai nella home dell’applicazione su Parse, vedrai che si è aggiunta la classe User e l’utente appena registrato:

Dashboard Parse e Login Utente

Vediamo un po’ nel dettaglio le proprietà della classe:

  • objectId: Il codice univoco che identifica l’utente. Viene creato automaticamente da Parse per ogni oggetto presente nella classe.
  • username: Il nome utente.
  • password: Nota come non viene visualizzata la password dell’utente. Infatti neanche l’amministratore della pagina può visualizzare i valori delle password inserite dai propri utenti. La password è cryptata e non su internet, durante l’invio dall’app al server e viceversa, non verrà mai visualizzata nella forma naturale ma solo e solamente in modalità cryptata. Questo è una delle caratteristiche a favore del servizio offerto da Parse Online.
  • authData: La data di autenticazione dell’utente, quando l’utente loggherà creando una nuova sessione, verrà inserita la data del relativo accesso.
  • emailVerified: Parse offre la possibilità di abilitare il servizio di autenticazione tramite link inviato per email, se vai nella pagina Settings, puoi abilitare quest’opzione.
    In questo modo l’utente sarà registrato solamente quando avrà convalidato l’account tramite email. Un altro punto a favore di Parse :P
  • createAt e updateAt: Le rispettive date di creazione e aggiornamento dell’account.

Come puoi notare, solamente 3, delle 6 proprietà della classe, sono state create da te. Le altre (non considerando emailVer e authData) vengono aggiunte in automatico in qualsiasi classe che creerai su Parse.

condividi xCoding

Ho impiegato un po’ di tempo a scrivere questo tutorial, sarei davvero felice se contribuissi al mio progetto semplicemente mettendo un mi piace o follow alle mie pagine

[addtoany]

[mailmunch-form id=”101287″]

Grazie davvero :-)

Il login online di un utente tramite Parse

Fatto l’account, bisogna fare il login.

Passa alla LoginViewController.swift e, nella IBAction login_clicked, aggiungi il seguente codice:

    @IBAction func login_clicked(sender: UIButton) {
        
        // eseguo un check sulle textfield
        guard let username = self.field_username.text else { return }
        guard let password = self.field_password.text else { return }
        
        // invoco il metodo della classe PFUser, logInWithUsernameInBackground
        // anche in questo caso viene utilizzata una closure con due argomenti,
        // user e error.
        // Se user è diverso da nil, ovvero esiste, allora è stato loggato.
        // altrimenti, se è uguale a nil, non esiste o è stato generato un errore.
        PFUser.logInWithUsernameInBackground(username, password: password) { (user, error) -> Void in
            if user != nil {
                print("[PARSE] Login effettuato con successo")
                self.performSegueWithIdentifier("segueToHome", sender: self)
            } else {
                print("[ERROR] login with error: \(error!.description)")
            }
        }
    }

Questa volta, pur essendo simile al metodo utilizzato per il signup, il metodo del login viene invocato direttamente dalla classe PFUser (mentre quello del signup dall’oggetto PFUser creato).

Anche questo metodo è di tipo asincrono e non bloccherà l’esecuzione del resto dell’applicazione.

Con l’account che hai creato, prova ad effettuare il login:

test login with parse and swift

Et voilà! finalmente hai creato un sistema di login online.

Il Current User, evitare il login per sessioni già esistenti

Immagina di utilizzare l’app più volte durante la giornata e quindi di doverla chiudere e riaprire N volte, genererebbe molto odio nei tuoi confronti il dover rieseguire il login ad ogni avvio dell’applicazione.

Per diminuire il numero di programmatori sgozzati, Parse ha introdotto un sistema per evitare il login dello stesso utente più volte nello stesso periodo.

Esiste un modo per poter verificare se un utente è ancora loggato oppure no, e consiste nel verificare se l’ultimo utente loggato ha ancora del tempo a disposizione per completare la sua sessione di attività. Il tempo viene suddiviso in sessioni (o quanto di tempo), ad esempio 3 ore dall’automatico login effettuato, e in ogni sessione l’utente rimane in background fin quando non viene scollegato o dalla fine della sessione o dall’invocazione di un metodo di logout.

Per poter utilizzare questa proprietà, nel file LoginViewController.swift, sotto la definizione della classe, aggiungi la seguente variabile:

    // controllo se l'ultimo utente loggato ha ancora del tempo a disposizione
    // per completare la sua sessione ed evitare la comparsa del modulo di login
    var currentUser :PFUser?

Nel metodo viewDidLoad, aggiungi il controllo sulla variabile currentUser:

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // chiamo il metodo currentUser che recupera l'istanza dell'ultimo utente loggato
        currentUser = PFUser.currentUser()
        
        // se la variabile currentUser è diversa da nil
        // vuol dire che già c'è qualcuno loggato
        // altrimenti deve registrarsi o loggarsi
        
        guard let realCurrentUser = self.currentUser else {
            print("Non c'è nessun utente loggato. \n loggati o registrati")
            return
        }
        
        print("[Parse] l'utente \(realCurrentUser.username!) è ancora loggato")
        self.performSegueWithIdentifier("segueToHome", sender: self)
    }

Credo non ci sia nient’altro da aggiungere rispetto a quanto già scritto nel commento del codice.

Per far funzionare il performSegueWithIdentifier, devi inserire un NavigationController prima del LoginViewController. Per farlo, ti basta selezionare il LoginViewController, cliccare in alto nel menu, il tasto Editor, poi Embed In e Navigation Controller.

Adesso non ti resta che provare!

test currentUser with parse and swift xcodeIl logout del current user

Per eseguire il logout ti basta utilizzare questo semplice codice:

PFUser.logOut()

Questo farà in modo che, quando reinvocherai il metodo currentUser, esso ritornerà nil.

In ogni caso dopo un paio d’ore, o dopo un giorno (onestamente non ricordo la durata di una sessione), l’account verrà scollegato in automatico. Con le opportune modifiche, potresti creare un timer in Swift che provvede a scollegare automaticamente l’account dopo un certo tot di tempo.

Considerazioni

Il prossimo passo dovrebbe essere quello di collegare le informazioni generiche, ad esempio quelle della lista della spesa, ad un utente, in modo da creare delle relazioni Utente-Oggetti o relationship one-to-many e many-to-many (il link porta ad una spiegazione analoga utilizzata per il core data).

Comunque, Parse è uno strumento efficiente quando si vogliono realizzare applicazioni cloud based e multipiattaforma. Tra le altre cose permette la gestione delle informazioni in locale quando la connessione è assente che evita tantissimi problemi di sincronizzazione in determinate situazioni.

Nel prossimo tutorial cercherò di trattare meglio la questione dei PFObject e delle query per il recupero dei dati.

Dove andare da qui

I tutorial che ti consiglio sono i seguenti:

Download del progetto finale

Se hai avuto problemi con il tuo progetto, qui sotto puoi scaricare quello fatto da me:

[sociallocker][wpdm_package id=’4326′][/sociallocker]

Buona Programmazione!