[iOS] Googleカレンダーのログイン認証をGIDSignInに移行する

こんにちは。カイザーです。

今年の4月にWebViewを使用した従来のGoogleログインは使用できなくなり、GIDSignInなどを使用する必要が出てきました。
WebViewでは、普段ユーザが使用しているログイン情報を使用することができず、アプリ毎にユーザがログイン情報を入力する必要があり、煩わしいためです。
そこで、URLスキームを使って普段使用するWebブラウザを使用させるか、WKWebViewなどのWebブラウザとログイン情報を共有出来る方法に移行するわけです。

GIDSignInは、この新しいログイン周りが簡単に行うことができるGoogle公式のライブラリです。WKWebViewを使用します。
今回は、従来の認証からGIDSignInに移行し、Googleカレンダーで使用する、という想定で進めていきます。

1. まずは導入

下記URLに従って導入します。とりあえずログインは出来るようになります。
https://developers.google.com/identity/sign-in/ios/sign-in?ver=swift
その際、以前の「GTMOAuth2ViewControllerTouch」でログインしていた処理は削除してください。

2. ログイン結果を通知

以前は、該当のViewControllerでログイン結果を受け取ることができましたが、今回はAppDelegateで行うようになっています。
そのため、AppDelegateからNotificationを使ってViewControllerに受け渡します。

AppDelegate.swift

extension Notification.Name {
static let googleSignInSuccess = Notification.Name("googleSignInSuccess")
static let googleSignInFailed = Notification.Name("googleSignInFailed")
}

AppDelegate.swift

func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
withError error: NSError!) {
if let _ = error {
// サインインが失敗
NotificationCenter.default.post(name: .googleSignInFailed, object: nil)
} else {
// サインインが成功
NotificationCenter.default.post(name: .googleSignInSuccess, object: nil)
}
}

これで、サインインできた時に通知するところまではできました。

3. ログイン結果の受け取り

あとは、受け取る側のViewControllerでNotificationの受け取りを設定します。失敗の場合はエラー表示します。
LoginViewController.swift

var service: GTLServiceCalend

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(loginSuccess), name: .googleSignInSuccess, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(loginFailed), name: .googleSignInFailed, object: nil)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

func loginSuccess() {
// ログイン成功
}

func loginFailed() {
let alert = UIAlertController(title: "ログインエラー", message: nil, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
present(alert, animated: true, completion: nil)
service?.authorizer = nil
setGoogleAccountLabelText(nil)
}

4. カレンダーAPIのリクエスト


// これは以前と同じです
private let service = GTLServiceCalendar()
func fetchEvents() {
// セッション切れになっているかもしれないので、再ログインしておく
GIDSignIn.sharedInstance().signInSilently()
if let auth = GIDSignIn.sharedInstance().currentUser {
// 以前「GTMOAuth2ViewControllerTouch」から取得していた認証情報は、「auth.authentication.fetcherAuthorizer()」で取得できる。
service.authorizer = auth.authentication.fetcherAuthorizer()
}
// カレンダーのイベントを取得します。service.authorizerに認証情報が入っているため、以前と同じように使えます。カレンダーイベント取得後「finishedWithObject」が呼ばれます。
let query = GTLQueryCalendar.queryForEventsList(withCalendarId: "カレンダーID")
let calendar = Calendar.current
var components = (calendar as NSCalendar).components([.day, .month, .year], from: selectedDate)
components.month? -= 1
var date = calendar.date(from: components)
query?.timeMin = GTLDateTime(date: date, timeZone: TimeZone.autoupdatingCurrent)
query?.singleEvents = true
query?.orderBy = kGTLCalendarOrderByStartTime
service.executeQuery(
query!,
delegate: self,
didFinish: #selector(CalenderViewController.displayResultWithTicket(_:finishedWithObject:error:))
}

ここでポイントになるのが、以前から使用していた「GTLServiceCalendar().authorizer」と、「GIDSignIn.sharedInstance().currentUser.authentication.fetcherAuthorizer()」が同じinterfaceを適用しているので、キャスト可能であるということです。

これは特に文献がなかったので、宣言部をひたすら見て行くしかなかったですね。。(GTLSercieとGIDSignInは両方ともObjective-Cで書かれているので、ヘッダファイルを見ていきます。)

まとめ

GIDSignInに切り替えても、従来のGTLServiceは利用可能。
ちなみに、AndroidはWebViewログインを行わず、OSの機能でログインできるので対応は不要です。

GoogleのAPIを使用していて、まだWebViewで認証している方は、急いで移行してください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です