Swift & Parseを使ったユーザー登録、ログイン、ログアウト（Swift, Xcode6 beta5,Parse）


![loginAndLogout.png](https://qiita-image-store.s3.amazonaws.com/0/27810/2899b190-94c7-d3dc-f7c1-831cc00f20c2.png "loginAndLogout.png")

# A. 概要
- MBaaSのParse.comを利用して、Swiftでユーザー登録とログイン・ログアウト処理を作ってみる


# B. 環境
- Xcode6 beta5
- Swift
- Parse.com

# C. Github
- [SwiftAndParseApp](https://github.com/kiiita/SwiftAndParseApp)
 - 今回の記事に関するコミットは以下の2つ
 - [Create Login and Logout function](https://github.com/kiiita/SwiftAndParseApp/commit/00a64fa1e8db97640b3130cfc53a79da6af451a6)
 - [Add a status about current user](https://github.com/kiiita/SwiftAndParseApp/commit/a5f870b9c17f5e2feaa6cd09a428a64aec465ee2)

# 1.ユーザー登録のためのポップアップを作る
- まずFirstViewが読み込めれる際に、ログイン済みのユーザーかどうかを判定
- ログインしていなければ、ユーザー登録用のAlertを表示する

```TimelineTableViewController.swift
    override func viewDidAppear(animated: Bool) {
        
        if (!PFUser.currentUser()) {
        
            var loginAlert:UIAlertController = UIAlertController(title: "Sign UP / Loign", message: "Plase sign up or login", preferredStyle: UIAlertControllerStyle.Alert)
            
            loginAlert.addTextFieldWithConfigurationHandler({
                textfield in
                textfield.placeholder = "Your username"
            })
            
            loginAlert.addTextFieldWithConfigurationHandler({
                textfield in
                textfield.placeholder = "Your Password"
                textfield.secureTextEntry = true
            })
            
            loginAlert.addAction(UIAlertAction(title: "Login", style: UIAlertActionStyle.Default, handler: {
                    alertAction in
                    let textFields:NSArray = loginAlert.textFields as NSArray
                let usernameTextfield:UITextField = textFields.objectAtIndex(0) as UITextField
                let passwordTextfield:UITextField = textFields.objectAtIndex(1) as UITextField

                var tweeter:PFUser = PFUser()
                tweeter.username = usernameTextfield.text
                tweeter.password = passwordTextfield.text
  				
                tweeter.signUpInBackgroundWithBlock{
                    (success:Bool!, error:NSError!)->Void in
                    if !error{
                        println("Sign up succeeded!")
                    }else{
                        let errorString = error.userInfo["error"] as NSString
                        println(errorString)
                    }
                }
              
                
                }))
            
            self.presentViewController(loginAlert, animated: true, completion: nil)
        }else{
            self.currentUsername.text = "Logged in as \(PFUser.currentUser().username)"
        }
    }
```

# 2. ユーザー登録とログインを関数を作る
```TimelineTableViewController.swift
    func signIn(username:NSString, password:NSString) {
        PFUser.logInWithUsernameInBackground(username, password: password) {
            (user: PFUser!, error: NSError!) -> Void in
            if user {
                println("existed user")
            } else {
                println("not existed user")
            }
        }
    }
    
    func signUp(tweeter:PFUser) {
        tweeter.signUpInBackgroundWithBlock{
            (success:Bool!, error:NSError!)->Void in
            if !error{
                println("Sign up succeeded.")
            }else{
                let errorString = error.userInfo["error"] as NSString
                println(errorString)
            }
        }
    }
```

# 3. 既にアカウントが登録されているかどうかをチェックする
```TimelineTableViewController.swift

// 1.に書かれていた下記のコードを消す
tweeter.signUpInBackgroundWithBlock{
	(success:Bool!, error:NSError!)->Void in
		if !error{
			println("Sign up succeeded!")
		}else{
			let errorString = error.userInfo["error"] as NSString
			println(errorString)
		}
}

// 上記コードの部分に下記を追記
// Check already registerd user
var checkExist = PFUser.query()
checkExist.whereKey("username", equalTo: tweeter.username) // usernameをキーにしてDBを検索
checkExist.findObjectsInBackgroundWithBlock {
	(objects: [AnyObject]!, error: NSError!) -> Void in
		if(objects.count > 0){
	 		println("its username is already taken \(objects.count)")
			self.signIn(tweeter.username, password:tweeter.password) // Login for already registerd user
		} else {                                                    
			println("its username hasn't token yet. Let's register!")
			self.signUp(tweeter) // Sign up for new user
		}                       
}
```

# 4. ログインステータスをViewに表示する
## 4-1. ラベルの用意
- class TimelineTableViewController: UITableViewControllerの直下に下記を追加（StoryBoardから持ってくる）

```TimelineTableViewController.swift
class TimelineTableViewController: UITableViewController {
    @IBOutlet var currentUsername: UILabel!
    ...
```

## 4-2. ラベルにtextを代入する
- ログイン前とログイン後で表示するテキストを変える

```TimelineTableViewController.swift
    override func viewDidAppear(animated: Bool) {
        
        // twwetのデータを取得
        self.loadData()
        
        // ログイン、サインアップのアラート
        if (!PFUser.currentUser()) {   
            self.currentUsername.text = "You aren't logged in now." // ココを追加
            var loginAlert:UIAlertController = UIAlertController(title: "Sign UP / Loign", message: "Plase sign up or login", preferredStyle: UIAlertControllerStyle.Alert)

			...

                // Check already registerd user
                var checkExist = PFUser.query()
                checkExist.whereKey("username", equalTo: tweeter.username) // usernameをキーにしてDBを検索
                checkExist.findObjectsInBackgroundWithBlock {
                    (objects: [AnyObject]!, error: NSError!) -> Void in
                    if(objects.count > 0){
                        println("its username is taken \(objects.count)")
                        self.signIn(tweeter.username, password:tweeter.password) // Login for already registerd user
                    } else {                                                    
                        println("its username hasn't token yet. Let's register!")
                        self.signUp(tweeter) // Sign up for new user
                    }                       
                }
                self.currentUsername.text = "Logged in as \(tweeter.username)" // ココを追加
                
                }))
            
            self.presentViewController(loginAlert, animated: true, completion: nil)
        }else{
            self.currentUsername.text = "Logged in as \(PFUser.currentUser().username)" // ココを追加
        }
```

# 5. ログアウト処理
## 5-1. TimelineTableViewControllerの他にもう1つあるComposeViewControllerにログアウト用のボタンを追加

```ComposeViewController.swift
    // Signout
    @IBAction func signOut(sender: AnyObject) {
        PFUser .logOut() // ログアウトの処理はこれだけでOK
       }
```

# 5-2. 処理が終わったらメインのView（TimelineTableViewController）に戻るようにする

```ComposeViewController.swift
    // Signout
    @IBAction func signOut(sender: AnyObject) {
        PFUser .logOut()
        // Go back to a root view if the button was clicked
        self.navigationController.popToRootViewControllerAnimated(true)
    }
```
- これでログアウトしたらメイン画面に戻って、再度ログインが求められるようになりました。

# D. 関連記事
- このログイン機能を使ってTwitterのような、ポストとタイムラインをつくてみたもの
 - [mBaaSを使ってみよう！超簡単にSwiftでTwitterライクなポスト機能を作る(Xcode6 beta5, Parse.com)](http://qiita.com/kiiita/items/bc62293f6c4d479993c1)
- その他、Swiftで作ってみたもの
 - [SwiftのNotificationでHello, Worldして、アクションを3つ作ってみた(Xcode6 beta4)](http://qiita.com/kiiita/items/453426e3873e58dc8768)
 - [SwiftでTo Doリストを作ってみた（Xcode6 beta4, Tabbed Application, UITableView, UITextField）](http://qiita.com/kiiita/items/22bcb7c503eaa2f2d423)

# E. 次にやってみたいこと
- validationとエラーメッセージ
- Tweet内容の削除、編集
- pull to refreshでリロード

雑多なコードなので、是非pull reqお願い致しますm(_ _)m  -> [SwiftAndParseApp](https://github.com/kiiita/SwiftAndParseApp) by @kiiita

---

★女性エンジニア向けのイベントやります
<a class="doorkeeper-registration-widget" href="http://zigexn.doorkeeper.jp/events/14687">9/17(水)開催 - ZIGExN Swift Girls 〜集え☆iPhoneアプリを作りたい女子〜</a><script src="http://widgets.doorkeeper.jp/w/widget.js"></script>