[Swift + Parse.com] アプリ開発（認証編）

SwiftとParse.comを使って簡単なブログアプリ開発します。

**まずは、認証編です。**


#認証種類
・Parse.comの独自認証
・Facebook認証
・Twitter認証

#画面遷移
##Parse.comの独自認証
①新規登録時
![screenshot_06.png](https://qiita-image-store.s3.amazonaws.com/0/38739/43a4df86-6b0b-996f-ccb3-9fbb57734a50.png)  ⇨  ![screenshot_07.png](https://qiita-image-store.s3.amazonaws.com/0/38739/23e5fa12-bdeb-96ff-dce7-5f5c2b4c3716.png)  ⇨  ![screenshot_08.png](https://qiita-image-store.s3.amazonaws.com/0/38739/831c063b-2b0c-7454-c47a-f6eef5674469.png)
※パスワードは６文字以上入力します。

②ログイン時
![screenshot_10.png](https://qiita-image-store.s3.amazonaws.com/0/38739/f7fe7ffe-8d80-76d0-81dc-b2c77bf5559a.png)  ⇨  ![screenshot_08.png](https://qiita-image-store.s3.amazonaws.com/0/38739/30dde7ca-b24c-d5fc-0353-d3523a1fdbb0.png)

##Facebook認証
![screenshot_15.png](https://qiita-image-store.s3.amazonaws.com/0/38739/a19b7ef2-b1fd-1e2f-f002-d468cd68834f.png)  ⇨  ![screenshot_16.png](https://qiita-image-store.s3.amazonaws.com/0/38739/556d660a-3e3e-710c-4153-829899a82bde.png)  ⇨  ![screenshot_18.png](https://qiita-image-store.s3.amazonaws.com/0/38739/0bda5755-472d-88ce-b462-866c6fb5238a.png)

##Twitter認証
![screenshot_21.png](https://qiita-image-store.s3.amazonaws.com/0/38739/b34a1205-64b5-3830-f188-1dd41b580dd0.png)  ⇨  ![screenshot_22.png](https://qiita-image-store.s3.amazonaws.com/0/38739/65905bf3-a1a3-b7fa-150e-75de326b75f2.png)  ⇨  ![screenshot_23.png](https://qiita-image-store.s3.amazonaws.com/0/38739/e1d04c72-88dc-f543-3077-d9b1b3f60ba1.png)




#事前準備
以下のサイトを参考し、Parse.comへの接続テストまで完了します。
[【参考】mBaaSを使ってみよう！超簡単にSwiftでTwitterライクなポスト機能を作る](http://qiita.com/kiiita/items/bc62293f6c4d479993c1)

#Parse.comの独自認証
PFLogInViewControllerを使用するため、「プロジェクト名-Bridging-Header.h」ファイルにParseUIを追加します。

```swift:プロジェクト名-Bridging-Header.h
#import <ParseUI/ParseUI.h>
```

フレームワークを追加します。
・Social.framework
・Accounts.framwork
**※追加しないと、ビルドエラーが発生するので注意！**
![screenshot_04.png](https://qiita-image-store.s3.amazonaws.com/0/38739/7ccf68a1-6a45-880e-9e78-e195dde32d93.png)


##新規プロジェクトの作成
storyboardを開き、UILabelとUIButtonを追加し、loginLabelとloginOrLogoutメソッドへ紐付けます。
![screenshot_03.png](https://qiita-image-store.s3.amazonaws.com/0/38739/e005d145-003d-061d-bd4e-1046523a2cc9.png)

LoginとSignUp処理を実装します。

```swift:ViewController.swift
//
//  ViewController.swift
//  ParseLoginSample

import UIKit

class ViewController: UIViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate {

    @IBOutlet weak var loginLabel: UILabel!
    @IBOutlet weak var loginBtn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

// 接続確認テスト
//        var testObject = PFObject(className: "TestObject")
//        testObject.setObject("bar", forKey: "foo")
//        testObject.saveInBackgroundWithBlock({(success, error) in
//            if success {
//                println("登録しました。")
//            } else {
//                println("登録失敗しました。")
//            }
//        })
    }

    override func viewWillAppear(animated: Bool) {
        // ログインしていない場合
        if PFUser.currentUser() == nil {
            loginLabel.text = "ログインしていません。"
            loginBtn.setTitle("login", forState: .Normal)
        } else {
            loginLabel.text = "\(PFUser.currentUser().username) ログイン中"
            loginBtn.setTitle("logout", forState: .Normal)
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func loginOrLogout(sender: AnyObject) {
        // loginボタンクリック時実装
        if PFUser.currentUser() == nil {
            login()
        } else {
            logout()
        }
    }

    // ログイン処理
    func login() {
        // Customize the LogInViewController
        let login = PFLogInViewController()
        login.delegate = self
        login.fields = (PFLogInFields.UsernameAndPassword
            | PFLogInFields.LogInButton
            | PFLogInFields.SignUpButton
            | PFLogInFields.PasswordForgotten
            | PFLogInFields.DismissButton)
        
        // Customize the SignUpViewController
        let signup = PFSignUpViewController()
        signup.fields = (PFSignUpFields.UsernameAndPassword
            | PFSignUpFields.SignUpButton
            | PFSignUpFields.Email
            | PFSignUpFields.DismissButton)
        signup.delegate = self
        login.signUpController = signup
        
        self.presentViewController(login, animated: true, completion: nil)
    }

    // ログアウト処理
    func logout() {
        PFUser.logOut()
        loginLabel.text = "ログインしていません。"
        loginBtn.setTitle("login", forState: .Normal)
    }

    // MARK: - PFLogInViewControllerDelegate

    func logInViewController(logInController: PFLogInViewController!, shouldBeginLogInWithUsername username: String!, password: String!) -> Bool {
        // ユーザ名とパスワードのチェック
        if !username.isEmpty && !password.isEmpty {
            return true
        }
        let alert = UIAlertView(title: "認証エラー", message: "ユーザもしくはパスワード入力が間違っています。", delegate: self, cancelButtonTitle: "キャンセル")
        alert.show()
        return false
    }
    
    func logInViewController(logInController: PFLogInViewController!, didLogInUser user: PFUser!) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func logInViewController(logInController: PFLogInViewController!, didFailToLogInWithError error: NSError!) {
        println("Failed to log in...")
    }
    
    func logInViewControllerDidCancelLogIn(logInController: PFLogInViewController!) {
        println("User dismissed the logInViewController")
    }

    // MARK: - PFSignUpViewControllerDelegate
    
    func signUpViewController(signUpController: PFSignUpViewController!,
        shouldBeginSignUp info: [NSObject : AnyObject]!) -> Bool {

            // パスワードが６文字以下はNG
            if let password = info?["password"] as? String {
                return password.utf16Count >= 6
            }
            return false
    }
    
    func signUpViewController(signUpController: PFSignUpViewController, didSignUpUser user: PFUser) -> Void {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func signUpViewControllerDidCancelSignUp(signUpController: PFSignUpViewController) -> Void {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func signUpViewController(signUpController: PFSignUpViewController!, didFailToSignUpWithError error: NSError!) {
        println("Failed to sign up...")
    }
}
```
ログイン・サインアップクラス
・PFLoginViewController
・PFSignUpViewController
・PFLogInViewControllerDelegate
・PFSignUpViewControllerDelegate

シミュレーターを起動し、動作確認します。

#Facebook認証
##Facebook DevelopersよりAppを登録
[Facebook Developers](https://developers.facebook.com/)
![screenshot_11.png](https://qiita-image-store.s3.amazonaws.com/0/38739/82cd1c5c-a856-9c08-23a5-ff61096e8ae5.png)
App IDとApp Secretをメモします。

##Parse.comの設定画面を開き、さきほどメモしたApp IDとApp Secretを設定
![screenshot_12.png](https://qiita-image-store.s3.amazonaws.com/0/38739/c2f60fbc-dae5-1081-8596-98bc3e2bc468.png)

##iOS用Facebook SDKをインストール
インストール後、~{ユーザ}/Documents/FacebookSDK.frameworkをプロジェクトへ取込む。
![screenshot_13.png](https://qiita-image-store.s3.amazonaws.com/0/38739/e895e5fb-8b6b-c652-21b8-c8cfefa84886.png)


FacebookSDKを使用するためにヘッダーファイルへ追加します。

```swift:プロジェクト名-Bridging-Header.h
#import <FacebookSDK/FacebookSDK.h>
#import <ParseFacebookUtils/PFFacebookUtils.h>
```
##build settings
info.plistに作成したFacebookアプリのAPP IDを設定します。
①key = "FacebookAppID", type = String, value = your AppID
②key = "FacebookDisplayName", type = String, value = your App Name
③key = URL types = Array, dictionary-type child. That dictionary's child:
④key = URL Schemes, type = Array. The Array's child: type = String, value = "fb" + AppID
![screenshot_17.png](https://qiita-image-store.s3.amazonaws.com/0/38739/3dd279b0-3a88-5108-1113-669436456323.png)


##ViewController.swiftのloginメソッド修正

```swift:ViewController.swift

    // ログイン処理
    func login() {
        // Customize the LogInViewController
        let login = PFLogInViewController()
        login.delegate = self
        login.fields = (PFLogInFields.UsernameAndPassword
            | PFLogInFields.LogInButton
            | PFLogInFields.SignUpButton
            | PFLogInFields.PasswordForgotten
            | PFLogInFields.Facebook
            | PFLogInFields.DismissButton)
        
        // Customize the SignUpViewController
        let signup = PFSignUpViewController()
        signup.fields = (PFSignUpFields.UsernameAndPassword
            | PFSignUpFields.SignUpButton
            | PFSignUpFields.Email
            | PFSignUpFields.DismissButton)
        signup.delegate = self
        login.signUpController = signup
        
        self.presentViewController(login, animated: true, completion: nil)
    }
```
login.fieldsにPFLogInFields.Facebookを追加します。

シミュレーターを起動し、動作確認します。

#Twitter認証
##Twitter DevelopersよりAppを登録
![screenshot_20.png](https://qiita-image-store.s3.amazonaws.com/0/38739/8038582f-1c7a-50a0-1c29-456717755557.png)

上記APIキーをメモ

##AppDelegate.swiftの修正
```swift:AppDelegate.swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Parse.com設定
        Parse.setApplicationId("アプリケーションID", clientKey: "クライアントキー")

        // facebook初期化
        PFFacebookUtils.initializeFacebook()

        // dev.twitter.comで登録したキーを設定
     PFTwitterUtils.initializeWithConsumerKey("API Key", consumerSecret: "API Secret")
        return true
    }
```
PFTwitterUtils.initializeWithConsumerKeyを追加し、さきほどメモしたAPIキーを設定します。

##ViewController.swiftのloginメソッド修正

```swift:ViewController.swift

    // ログイン処理
    func login() {
        // Customize the LogInViewController
        let login = PFLogInViewController()
        login.delegate = self
        login.fields = (PFLogInFields.UsernameAndPassword
            | PFLogInFields.LogInButton
            | PFLogInFields.SignUpButton
            | PFLogInFields.PasswordForgotten
            | PFLogInFields.Facebook
            | PFLogInFields.Twitter
            | PFLogInFields.DismissButton)
        
        // Customize the SignUpViewController
        let signup = PFSignUpViewController()
        signup.fields = (PFSignUpFields.UsernameAndPassword
            | PFSignUpFields.SignUpButton
            | PFSignUpFields.Email
            | PFSignUpFields.DismissButton)
        signup.delegate = self
        login.signUpController = signup
        
        self.presentViewController(login, animated: true, completion: nil)
    }
```
login.fieldsにPFLogInFields.Twitterを追加します。

シミュレーターを起動し、動作確認します。

以上。

サンプルプロジェクトをGitHubにアップしました。
[GitHub](https://github.com/bongkook/ParseLoginSample)

次回にはアプリ開発（本編）を掲載します。