In questa lezione verranno illustrati i passi necessari per realizzare una schermata di autenticazione che sfrutti il social login tramite Google, a partire da un progetto realizzato con Xcode.
Il codice necessario sarà mostrato sia in linguaggio Swift, sia utilizzando Objective-C.
Configurazione del PodFile
Per iniziare l’integrazione, il primo passo da compiere è l’aggiunta della SDK di Google attraverso la modifica del Podfile inizializzato in precedenza.
Apriamo il Podfile con un qualsiasi editor di testo e aggiungiamo la SDK di Google per il login nell’apposita sezione, ottenendo:
target 'SocialLoginHMTLit' do
use_frameworks!
# Pods for SocialLoginHMTLit
pod 'GoogleSignIn'
end
Una volta salvato e chiuso il file, da terminale eseguiamo il comando
pod install
per effettuare l’installazione delle librerie nel nostro progetto e per la creazione del workspace da usare al posto del progetto base appena creato. In caso di corretta installazione, il terminale mostrerà un output simile al seguente:
Ora che le librerie sono state correttamente integrate nel progetto, apriamo il workspace SocialLoginHMTLit.xcworkspace.
Aggiunta del file GoogleService-Info.plist
Diversamente dalle altre piattaforme social come Facebook, il file Info.plist non deve essere modificato in quanto va aggiunto il file GoogleService-Info.plist ottenuto durante la registrazione dell’applicazione alla Google Developer Console.
Una volta scaricato il file GoogleService-Info.plist, posizioniamolo nella root del progetto come mostrato in figura.
Al suo interno sono memorizzate diverse informazioni, quali:
- informazioni sul progetto;
- informazioni sul client, come il client ID, il reversed client ID e il bundle ID.
Per abilitare l’applicazione ad utilizzare il meccanismo di autenticazione di Google, devono essere aggiunti due URL Scheme al progetto.
Nella sezione Info delle configurazioni del progetto, espandiamo la sezione URL Types e clicchiamo sul + riportando nella textbox dell’URL Schemes il reversed client ID (reperibile nel GoogleService-Info.plist). Ripetiamo la medesima operazione riportando questa volta il bundle ID. A seguito di queste due modifiche, otterremo il seguente risultato:
Modifica dell’AppDelegate
Per inizializzare l’SDK di Google all’avvio dell’applicazione, importiamo nell’AppDelegate
la classe GoogleSignIn
come segue:
Swift
import GoogleSignIn
Objective-C
//Nel file .h
@import GoogleSignIn;
La classe GoogleSignIn
offre il single sign-on tramite un’applicazione di Google già abilitata, o in assenza attraverso il browser.
Successivamente, va implementata la classe GIDSignInDelegate
che definisce un protocollo utilizzato dal delegato del GIDSignIn
. Al termine della comunicazione verrà restituito all’applicazione un nuovo token o, in caso di fallimento, un errore.
Swift
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
…
}
Objective-C
//Aggiungere nel file .h
@interface AppDelegate : UIResponder <UIApplicationDelegate, GIDSignInDelegate>
Inizializziamo il GIDSignIn
impostando il client ID e il delegate nel metodo application:didFinishLaunchingWithOptions:
.
Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
GIDSignIn.sharedInstance().clientID = "877271852566-2via6d1visno85ufb882rg1p4ha7r0oh.apps.googleusercontent.com"
GIDSignIn.sharedInstance().delegate = self
return true
}
Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GIDSignIn sharedInstance].clientID = @"877271852566-2via6d1visno85ufb882rg1p4ha7r0oh.apps.googleusercontent.com";
[GIDSignIn sharedInstance].delegate = self;
return YES;
}
Implementiamo ora il metodo application:openURL:options:
.
Swift
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
var options: [String: AnyObject] = [UIApplicationOpenURLOptionsSourceApplicationKey: sourceApplication,
UIApplicationOpenURLOptionsAnnotationKey: annotation]
return GIDSignIn.sharedInstance().handleURL(url, sourceApplication: sourceApplication, annotation: annotation)
}
Objective-C
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
return [[GIDSignIn sharedInstance] handleURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
}
Come è possibile notare, è stato invocato il metodo handleURL
dell’istanza GIDSignIn
per gestire correttamente l’URL inviata all’applicazione al termine del processo di autenticazione.
Infine, non resta che definire il metodo di login come segue:
Swift
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
...
NotificationCenter.default.post(
name: Notification.Name(rawValue: "ToggleAuthUINotification"),
object: nil,
userInfo: nil)
} else {
...
if let fullName = user.profile.name{
NotificationCenter.default.post(
name: Notification.Name(rawValue: "ToggleAuthUINotification"),
object: nil,
userInfo: ["statusText": "Hi \(fullName)!"])
}
}
}
Objective-C
- (void)signIn:(GIDSignIn *)signIn
didSignInForUser:(GIDGoogleUser *)user
withError:(NSError *)error {
…
NSString *fullName = user.profile.name;
NSDictionary *statusText = @{@"statusText": [NSString stringWithFormat:@"Hi %@", fullName]};
[[NSNotificationCenter defaultCenter] postNotificationName:@"ToggleAuthUINotification" object:nil userInfo:statusText];
}
Nel metodo proposto è stato definito un NotificationCenter
, che può essere visto come uno strumento di comunicazione tra classi sulla base delle azioni compiute nell’applicazione. Il NotificationCenter.default
(o NSNotificationCenter defaultCenter
) è il punto in cui tutte le notifiche sono inviate (tramite il metodo post
) e tenute sotto osservazione per essere consumate da un observer
.
Infine, sono stati impostati:
- il
postNotificationName
aToggleAuthUINotification
; - il campo
userInfo
astatusText
per la visualizzazione del nome utente.
Integrazione del bottone di login
Aggiungiamo, infine, il bottone di autenticazione nella schermata principale.
Nella Main.storyboard selezioniamo l'oggetto View dall’Object Library e posizioniamolo al centro della schermata. Impostiamo, poi, la classe della View
a GIDSignInButton
come mostrato in figura.
Avendo creato il bottone come un oggetto View
, questo non verrà visualizzato all’interno della schermata.
Colleghiamo poi il bottone di login con il codice del ViewController
per creare il seguente IBOutlet
Swift
@IBOutlet weak var signInButton: GIDSignInButton!
Objective-C
@property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
Nel corpo del metodo ViewDidLoad
, impostiamo lo UiDelegate
e il NotificationCenter
come segue:
Swift
override func viewDidLoad() {
...
GIDSignIn.sharedInstance().uiDelegate = self
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.receiveToggleAuthUINotification(_:)),
name: NSNotification.Name(rawValue: "ToggleAuthUINotification"),
object: nil)
...
}
Objective-C
- (void)viewDidLoad {
...
[GIDSignIn sharedInstance].uiDelegate = self;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(receiveToggleAuthUINotification:)
name:@"ToggleAuthUINotification"
object:nil];
...
}
In questo modo, abbiamo aggiunto un Observer
alla schermata corrente in modo da estrarre la userInfo
impostata nell’AppDelegate
attraverso il metodo receiveToggleAuthUINotification
impostato come selector
e implementato come segue:
Swift
@objc func receiveToggleAuthUINotification(_ notification: NSNotification) {
if notification.name.rawValue == "ToggleAuthUINotification" {
...
if notification.userInfo != nil {
guard let userInfo = notification.userInfo as? [String:String] else { return }
self.statusText.text = userInfo["statusText"]!
}
}
}
Objective-C
- (void) receiveToggleAuthUINotification:(NSNotification *) notification {
if ([notification.name isEqualToString:@"ToggleAuthUINotification"]) {
...
self.statusText.text = notification.userInfo[@"statusText"];
}
}
Aggiungiamo ora il bottone di logout.
Diversamente dalla SDK di Facebook, il bottone di login non verrà sostituito automaticamente da quello di logout. Analogamente a quanto fatto prima, nella Main.storyboard selezioniamo l'oggetto UIButton
dall’Object Library e posizioniamolo al centro della schermata. Successivamente, impostiamo il testo del bottone a Sign Out e lo sfondo a grigio attraverso la proprietà background dell’Attribute Inspector.
Colleghiamo poi il bottone con il codice del ViewController
per creare un IBOutlet
di tipo UIButton
e aggiungiamo un nuovo metodo per il logout da Google come segue.
Swift
@IBAction func didTapSignOut(_ sender: AnyObject) {
GIDSignIn.sharedInstance().signOut()
...
}
Objective-C
- (IBAction)didTapSignOut:(id)sender {
[[GIDSignIn sharedInstance] signOut];
...
[self toggleAuthUI];
}
Colleghiamo infine il bottone di logout al metodo didTapSignOut
.
Inseriamo ora una label di tipo UILabel
per mostrare il nickname dell’utente loggato, posizionandola sopra il bottone di logout e collegandola al codice, come fatto in precedenza.
Gestiamo infine, la visibilità dei bottoni creati e del testo della label attraverso il seguente metodo:
Swift
func toggleAuthUI() {
if GIDSignIn.sharedInstance().hasAuthInKeychain() {
signInButton.isHidden = true
signOutButton.isHidden = false
} else {
signInButton.isHidden = false
signOutButton.isHidden = true
statusText.text = "Google Sign in"
}
}
Objective-C
- (void)toggleAuthUI {
if ([GIDSignIn sharedInstance].currentUser.authentication != nil) {
self.signInButton.hidden = YES;
self.signOutButton.hidden = NO;
} else {
self.signInButton.hidden = NO;
self.signOutButton.hidden = YES;
self.statusText.text = @"Google Sign in";
}
}
Questa funzione, nasconderà il bottone di login in caso di login, mostrando quindi il bottone di logout. Contrariamente, in caso di fallimento, verrà visualizzato il bottone di login e reimpostato il testo della label.
Per completare le modifiche, richiamiamo il metodo toggleAuthUI
nei seguenti metodi:
viewDidLoad
;didTapSignOut
;receiveToggleAuthUINotification
.
Risultato finale
All’avvio dell’applicazione sul dispositivo mobile o sull’emulatore, verrà mostrata la schermata contenente il bottone di default precedentemente aggiunto all’interfaccia.
Cliccando sul bottone, verrà richiesto all’utente di autenticarsi con il proprio account Google e di accettare i termini del servizio.
Una volta autenticato, l’utente viene rimandato nuovamente alla scheramta di avvio dove sarà visualizzato il nome dell’utente e il bottone di logout, come in figura.
Cliccando sul bottone di sign out, l’utente verrà disconnesso.
Il codice sorgente di questa sezione è reperibile su GitHub, nel branch Google Login.