Swift3でGoogle Calendarから予定の取得

Swift3 で Google Calendar から予定を取得しようとした際に詰まったので、メモ程度にまとめます。
基本的には以下のサイトの通りです。

参考サイト
[Google Developer iOS Quickstart](https://developers.google.com/google-apps/calendar/quickstart/ios?ver=swift)

## OAuth client ID の取得
Step1 の手順に従って OAuth client ID を取得します。

## Podfileの作成
以下のように作成します。

```podfile:Podfile
use_frameworks!

target 'App Name' do
  pod 'GoogleAPIClient/Calendar', '~> 1.0.2'
  pod 'GTMOAuth2', '~> 1.1.0'
end

```

## Google Calendar から予定の取得
ほとんどサンプルコードからコンパイルエラーを修正していく感じですが、以下のように変更が必要です。

```diff
func fetchEvents() {
    let query = GTLQueryCalendar.queryForEventsList(withCalendarId: "primary")
    query?.maxResults = 10
    query?.timeMin = GTLDateTime(date: NSDate() as Date!, timeZone: NSTimeZone.local)
    query?.singleEvents = true
    query?.orderBy = kGTLCalendarOrderByStartTime
    service.executeQuery(
        query!,
        delegate: self,
-       didFinishSelector: "displayResultWithTicket:finishedWithObject:error:"
+       didFinish: #selector(ViewController.displayResultWithTicket(ticket:finishedWithObject: error:))
    )
}
```

```diff
private func createAuthController() -> GTMOAuth2ViewControllerTouch {
    let scopeString = scopes.joined(separator: " ")
    return GTMOAuth2ViewControllerTouch(
        scope: scopeString,
        clientID: kClientID,
        clientSecret: nil,
        keychainItemName: kKeychainItemName,
        delegate: self,
-       finishedSelector: "viewController:finishedWithAuth:error:"
+       finishedSelector: #selector(ViewController.viewController(vc: finishedWithAuth: error:))
    )
}
```

結果、こんな感じで予定を取得できます。
<img src=https://qiita-image-store.s3.amazonaws.com/0/87003/573f0ee4-2296-02c9-f5e3-0ed5cbb5f4db.png height=400>

ViewController.swift は以下の通りです。

```swift:ViewController
import GoogleAPIClient
import GTMOAuth2
import UIKit

class ViewController: UIViewController {
    private let kKeychainItemName = "Google Calendar API"
    private let kClientID = "CLIENT ID"
    
    // If modifying these scopes, delete your previously saved credentials by
    // resetting the iOS simulator or uninstall the app.
    private let scopes = [kGTLAuthScopeCalendarReadonly]
    
    private let service = GTLServiceCalendar()
    let output = UITextView()
    
    // When the view loads, create necessary subviews
    // and initialize the Google Calendar API service
    override func viewDidLoad() {
        super.viewDidLoad()
        
        output.frame = view.bounds
        output.isEditable = false
        output.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)
        output.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        
        view.addSubview(output);
        
        if let auth = GTMOAuth2ViewControllerTouch.authForGoogleFromKeychain(
            forName: kKeychainItemName,
            clientID: kClientID,
            clientSecret: nil) {
            service.authorizer = auth
        }
    }
    
    // When the view appears, ensure that the Google Calendar API service is authorized
    // and perform API calls
    override func viewDidAppear(_ animated: Bool) {
        if let authorizer = service.authorizer,
            let canAuth = authorizer.canAuthorize , canAuth {
            fetchEvents()
        } else {
            present(
                createAuthController(),
                animated: true,
                completion: nil
            )
        }
    }
    
    // Construct a query and get a list of upcoming events from the user calendar
    func fetchEvents() {
        let query = GTLQueryCalendar.queryForEventsList(withCalendarId: "primary")
        query?.maxResults = 10
        query?.timeMin = GTLDateTime(date: NSDate() as Date!, timeZone: NSTimeZone.local)
        query?.singleEvents = true
        query?.orderBy = kGTLCalendarOrderByStartTime
        service.executeQuery(
            query!,
            delegate: self,
            didFinish: #selector(ViewController.displayResultWithTicket(ticket:finishedWithObject: error:))
        )
    }
    
    // Display the start dates and event summaries in the UITextView
    func displayResultWithTicket(ticket: GTLServiceTicket, finishedWithObject response : GTLCalendarEvents, error : NSError?) {
        
        if let error = error {
            showAlert(title: "Error", message: error.localizedDescription)
            return
        }
        
        var eventString = ""
        
        if let events = response.items() , !events.isEmpty {
            for event in events as! [GTLCalendarEvent] {
                let start : GTLDateTime! = event.start.dateTime ?? event.start.date
                let startString = DateFormatter.localizedString(
                    from: start.date,
                    dateStyle: .short,
                    timeStyle: .short
                )
                eventString += "\(startString) - \(event.summary)\n"
            }
        } else {
            eventString = "No upcoming events found."
        }
        
        output.text = eventString
    }
    
    
    // Creates the auth controller for authorizing access to Google Calendar API
    private func createAuthController() -> GTMOAuth2ViewControllerTouch {
        let scopeString = scopes.joined(separator: " ")
        return GTMOAuth2ViewControllerTouch(
            scope: scopeString,
            clientID: kClientID,
            clientSecret: nil,
            keychainItemName: kKeychainItemName,
            delegate: self,
            finishedSelector: #selector(ViewController.viewController(vc: finishedWithAuth: error:))
        )
    }
    
    // Handle completion of the authorization process, and update the Google Calendar API
    // with the new credentials.
    func viewController(vc : UIViewController, finishedWithAuth authResult : GTMOAuth2Authentication, error : NSError?) {
        
        if let error = error {
            service.authorizer = nil
            showAlert(title: "Authentication Error", message: error.localizedDescription)
            return
        }
        
        service.authorizer = authResult
        dismiss(animated: true, completion: nil)
    }
    
    // Helper for showing an alert
    func showAlert(title : String, message: String) {
        let alert = UIAlertController(
            title: title,
            message: message,
            preferredStyle: UIAlertControllerStyle.alert
        )
        let ok = UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.default,
            handler: nil
        )
        alert.addAction(ok)
        present(alert, animated: true, completion: nil)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
```