Swiftでログイン機能をつけてみよう！

__【お知らせ】Swift3に対応しました！（2017/02/24更新）__

# 【Swift×mBaaS】シリーズ概要
* Swiftで[ニフティクラウドmobile backend](http://mb.cloud.nifty.com/)(通称：mBaaS)を使ってSwiftで開発を始めたい人向けのドキュメントです。
* [ニフティクラウドmobile backendのiOS(Objectiv-C SDK)用ドキュメント](http://mb.cloud.nifty.com/doc/current/index.html)を__Swift__用に書き換えて動かしてみたものをまとめました。
* 初心者でもわかりやすいよう心掛けて作っていますが、わかりにくい部分がありましたらコメントをいただければ訂正しますのでお気軽にご意見をお願いします^^*
* 今回は__＜会員管理編＞__です！

# 事前準備のお願い
* 事前にニフティクラウド[mobil backendの登録](http://mb.cloud.nifty.com/)とアプリの新規作成をし、 [＜CocoaPods＞SwiftでmBaaSを始めよう！(use_framewoks!を有効にした方法)](http://qiita.com/natsumo/items/57d3a4d9be16b0490965)をご覧いただき、必要な初期設定(SDKのインストールなど)をXcode上で行った上でご利用ください。



# 会員管理について
## 認証の種類
* 会員の認証方法は4つあります。
 * ユーザー名とパスワードによる認証
 * メールアドレスとパスワードによる認証
 * 匿名認証
 * SNSアカウント（Facebook/Twitter/Google）での認証
* ここでは上３つを扱います。
* 「SNSアカウントでの認証」については下記＜SNS連携編＞をご覧ください。
 *  [SwiftでFacebook連携しよう！](http://qiita.com/natsumo/items/f5c4d41edae17a4a75ce)
 *  SwiftでTwitter連携しよう！　※準備中
 *  SwiftでGoogle連携しよう！　※準備中


## ダッシュボードでの事前設定
ここで扱う３つの認証方法

 * ユーザー名とパスワードによる認証
 * メールアドレスとパスワードによる認証
 * 匿名認証

は、いずれにおいても__認証を許可する設定__を、[ニフティクラウドmobile backend](http://mb.cloud.nifty.com/)のダッシュボード上で行わなければなりません。

[ニフティクラウドmobile backend](http://mb.cloud.nifty.com/)にログインして、ブラウザでダッシュボードを開いてください。

* ユーザー名とパスワードによる認証とメールアドレスとパスワードによる認証は_アプリ設定_＞_会員認証設定_に設定項目があります。
* 匿名認証は_アプリ設定_＞_基本_の画面の下のほうに設定項目があります。

![図2.png](https://qiita-image-store.s3.amazonaws.com/0/112032/1a48780c-29df-a7ac-121e-3bf3457b028f.png)

* コードを実行する前に「__許可する__」に設定をして「__保存する__」ボタンで必ず保存をしおいてください。

# __Swiftでログイン機能をつけてみよう！__
* [ニフティクラウドmobile backend](http://mb.cloud.nifty.com/)のダッシュボードで確認をしながらXcodeで動作確認をしてください。
* ドキュメントの動作確認の方法については[Swiftでデータベースを使おう！①（保存・取得・更新・削除）](http://qiita.com/natsumo/items/c00cf7a48e0f8cd8d236)の「ドキュメントの動作確認方法」にまとめてありますので参考にしてみてください◎

## __ユーザー名・パスワード認証__
### ユーザーの新規登録
NCMBUserオブジェクト作成後、signUpInBackgroundWithBlockメソッドで登録処理を行います

```swift:Swift3
//NCMBUserのインスタンスを作成
let user = NCMBUser()
//ユーザー名を設定
user.userName = "user1"
//パスワードを設定
user.password = "password1"
//会員の登録を行う
user.signUpInBackground { (error) in
    if error != nil {
        // 新規登録失敗時の処理
    }else{
        // 新規登録成功時の処理
    }
}
```

```swift:Swift2
//NCMBUserのインスタンスを作成
let user = NCMBUser()
//ユーザー名を設定
user.userName = "user1"
//パスワードを設定
user.password = "password1"
//会員の登録を行う
user.signUpInBackgroundWithBlock{(error: NSError!) in
    if error != nil {
        // 新規登録失敗時の処理
    }else{
        // 新規登録成功時の処理
    }
}
```

### ログイン
logInWithUsernameInBackgroundメソッドに新規登録時に設定したユーザ名とパスワードを指定してログインします

```swift:Swift3
// ユーザー名とパスワードでログイン
NCMBUser.logInWithUsername(inBackground: "user1", password: "password1") { (user, error) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
}
```

```swift:Swift2
// ユーザー名とパスワードでログイン
NCMBUser.logInWithUsernameInBackground("user1", password: "password1", block:{(user: NCMBUser!, error: NSError!) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
})
```

* ログインをすると「セッショントークン」というものが発行されます。これによって特定のユーザーの権限でオブジェクトにアクセスできるようになります。

### ログアウト
logOutメソッドを利用します。

```swift:Swift_共通
// ログアウト
NCMBUser.logOut()
```

* ログアウトすることでセッショントークンは無効になります。
* セッショントークンはログアウトしなくてもデフォルトで24時間たつと無効になります。有効期限の変更は先程のダッシュボードで行えます。


### ログイン中のユーザーの取得
currentUserメソッドで、現在ログイン中のユーザー（カレントユーザー）情報を取得することができます。

```swift:Swift3
let carrentUser = NCMBUser.current()
```

```swift:Swift2
let carrentUser = NCMBUser.currentUser()
```

## __メールアドレス・パスワード認証__
メールアドレス認証は、

1. 利用者がメールアドレスを入力して認証をリクエストする
2. 入力したメールアドレスに対して会員登録画面へのURLを含むメールが送信される
3. メールから会員登録画面を開き、パスワードを入力して会員登録を行う
4. メールアドレスとパスワードでのログインが可能になる

という流れになっています。
※ 2.の送信元メールアドレスや、メール本文の内容は先程のダッシュボードで設定ができます。


### 会員登録用のメールを要求する
requestAuthenticationMailメソッドを実行すると、メールアドレスでの会員登録を行うためのメールが送信されます。

```swift:Swift3
NCMBUser.requestAuthenticationMail("test@sample.com", error: nil)
```

```swift:Swift2
var error : NSError? = nil
NCMBUser.requestAuthenticationMail("test@sample.com", error: &error)
```

* `"test@sample.com"`の部分をお持ちのメールアドレスに書き換えて試してみてください！

### ログイン
logInWithMailAddressInBackgroundメソッドに、登録時に設定したメールアドレスとパスワードを指定してログインします。

```swift:Swift3
// メールアドレスとパスワードでログイン
NCMBUser.logInWithMailAddress(inBackground: "test@sample.com", password: "password2", block: { (user, error) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
})
```

```swift:Swift2
// メールアドレスとパスワードでログイン
NCMBUser.logInWithMailAddressInBackground("test@sample.com", password: "password2", block:{(user: NCMBUser!, error: NSError!) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
})
```
* __ログアウト__はユーザー名・パスワード認証と同様です。

## __匿名認証__
ユーザー名・パスワードを入力せずに会員登録をすることができます。ただし、一度ログアウトをすると、次にログインする場合は別のユーザーとして登録されてしまうので、仮ユーザーとして利用する用途で使います。

### ログイン
NCMBAnonymousUtilsクラスを利用して、匿名ユーザーでログインします。

```swift:Swift3
// 匿名ユーザーでログイン
NCMBAnonymousUtils.logIn { (user, error) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
}
```

```swift:Swift2
// 匿名ユーザーでログイン
NCMBAnonymousUtils.logInWithBlock{(user: NCMBUser!, error: NSError!) in
    if error != nil {
        // ログイン失敗時の処理
    }else{
        // ログイン成功時の処理
    }
}
```

### ログイン中の匿名ユーザーの取得
isLinkedWithUserメソッドで匿名ユーザーでログインしているか確認できます。

```swift:Swift3
if NCMBAnonymousUtils.isLinked(with: NCMBUser.current()) {
    // 匿名ユーザーでログインしている時の処理
}else{
    // 匿名ユーザーでログインしていない時の処理
}
```

```swift:Swift2
if NCMBAnonymousUtils.isLinkedWithUser(NCMBUser.currentUser()) {
    // 匿名ユーザーでログインしている時の処理
}else{
    // 匿名ユーザーでログインしていない時の処理
}
```

## __会員のグルーピング（ロール）__
ロールは、会員をグルーピングするための機能です。

### ロールの作成
NCMBRoleクラスを利用します。

```swift:Swift3
// ロールの作成
let basicPlanRole = NCMBRole(name: "basicPlan")
basicPlanRole?.saveInBackground(nil)
let expertPlanRole = NCMBRole(name: "expertPlan")
expertPlanRole?.saveInBackground(nil)
```

```swift:Swift2
// ロールの作成
let basicPlanRole = NCMBRole(name: "basicPlan")
basicPlanRole.saveInBackgroundWithBlock(nil)
let expertPlanRole = NCMBRole(name: "expertPlan")
expertPlanRole.saveInBackgroundWithBlock(nil)
```

### 会員をロールに追加する
addUserメソッドを利用します。

```swift:Swift3
// ロールに追加するユーザーを作成
let user = NCMBUser()
user.userName = "basicPlanUser"
user.password = "password"
user.signUpInBackground { (error) in
    if error != nil {
        // ユーザー作成失敗時の処理
        
    }else{
        // ユーザー作成成功時の処理
        // 既存ロールの"basicPlan"を検索
        let query = NCMBRole.query()
        query?.whereKey("roleName", equalTo: "basicPlan")
        query?.findObjectsInBackground({ (objects, error) in
            if error != nil {
                // 検索失敗時の処理
            }else{
                // 検索成功時の処理
                // 検索結果をロールに設定してユーザーを追加
                let role = objects?[0] as! NCMBRole
                role.add(user)
                role.saveInBackground({ (error) in
                    if error != nil {
                        // ユーザー追加失敗時の処理
                    }else{
                        // ユーザー追加成功時の処理
                    }
                })
            }
        })
    }
}
```

```swift:Swift2
// ロールに追加するユーザーを作成
let user = NCMBUser()
user.userName = "basicPlanUser"
user.password = "password"
user.signUpInBackgroundWithBlock{(error: NSError!) in
    if error != nil {
        // ユーザー作成失敗時の処理
    }else{
        // ユーザー作成成功時の処理
        // 既存ロールの"basicPlan"を検索
        let query = NCMBRole.query()
        query.whereKey("roleName", equalTo: "basicPlan")
        query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]!, error: NSError!) -> Void in
            if error != nil {
                // 検索失敗時の処理
            }else{
                // 検索成功時の処理
                // 検索結果をロールに設定してユーザーを追加
                let role = objects.first
                role!.addUser(user)
                role!.saveInBackgroundWithBlock{(error: NSError!) -> Void in
                    if error != nil {
                        // ユーザー追加失敗時の処理
                    }else{
                        // ユーザー追加成功時の処理
                    }
                }
            }
        }
    }
}
```

### 子ロールの追加
* ロールの中にロールを作成します。

親ロールの中に子ロールを作成するには、addRoleメソッドを利用します。

```swift:Swift3
// 子ロール
let childRole = NCMBRole(name: "childRole")
childRole?.save(nil)
let role = NCMBRole(name: "Role")
role?.add(childRole)
role?.save(nil)
```

```swift:Swift2
// 子ロール
let childRole = NCMBRole(name: "childRole")
childRole.save(nil)
let role = NCMBRole(name: "Role")
role.addRole(childRole)
role.save(nil)
```