ログイン画面の実装

次に、ログイン画面の実装を説明します。LoginViewController.swift ファイルおよび LoginViewController.m ファイルに実装されています。

ログイン画面は、ストーリーボードで Navigation Controller の初めの画面として表示されるように設定されています。

画面の各要素は、ストーリーボードを介してクラス内の実装と次のように結びついています。

  • アウトレットによって、2 つの入力領域を LoginViewController クラスの usernameField プロパティと passwordField プロパティに関連付けます。

  • ボタンのアクションを signupButtonPressed(_:) メソッドと loginButtonPressed(_:) メソッドに設定します。

  • アウトレットによって Activity Indicator を activityIndicator に関連付けて、待機中のアニメーションを制御できるようにしています(以下、Activity Indicator の説明は省略しています)。

  • 画面がタップされたとき、キーボードが非表示になるように Tap Gesture Recoginizer を onTap(_:) メソッドに設定します。このメソッドでは編集終了の処理を行います。

  • マニュアルセグエ OpenMainPage を設定し、プログラム操作によってデータ一覧画面への遷移を行えるようにします。

ユーザー作成

初めに、ユーザー作成の処理を説明します。"Sign Up" ボタンがタップされると、signupButtonPressed(_:) メソッドが実行されます。このメソッドの処理を抜粋すると、以下のようになります(本質的ではない部分は削除しています)。

  • let username = usernameField.text!
    let password = passwordField.text!
    
    // Create a KiiUser object.
    let user = KiiUser(username: username, andPassword: password)
    
    // Register the user asynchronously.
    user.performRegistration { (user, error) -> Void in
      if error != nil {
        self.showMessage("Sign up failed", error: error as NSError?)
        return
      }
    
      // Go to the main screen.
      self.performSegue(withIdentifier: "OpenMainPage", sender: nil)
    }
  • NSString *username = self.usernameField.text;
    NSString *password = self.passwordField.text;
    
    // Create a KiiUser object.
    KiiUser *user = [KiiUser userWithUsername:username
                                  andPassword:password];
    
    // Register the user asynchronously.
    [user performRegistrationWithBlock:^(KiiUser *user, NSError *error) {
      if (error != nil) {
        [self showMessage:@"Sign up failed" error:error];
        return;
      }
    
      // Go to the main screen.
      [self performSegueWithIdentifier:@"OpenMainPage" sender:nil];
    }];
  1. ユーザー名とパスワードを iOS の UIKit フレームワークを使って画面から取得し、usernamepassword とします。

  2. ユーザー名とパスワードを渡してメモリ上に KiiUser インスタンスを作成します。

  3. performRegistration(_:) メソッドを呼び出します。指定されたユーザーを Kii Cloud 上に作成するリクエストが SDK からサーバーに送信されます。

ノンブロッキング API

ネットワーク呼び出しには時間がかかるため、performRegistration(_:) などの API は、ノンブロッキング API として実装されています。iOS のモバイルアプリでは、ユーザーインターフェイスの処理をメインスレッドが行っています。メインスレッドがネットワーク呼び出しで待ち状態になると、モバイルアプリ全体がフリーズしてしまいます。この問題を防止する仕組みがノンブロッキング API です。

逆に、API の実行完了まで待つのがブロッキング API です。ブロッキング API は自分で作業スレッドを作成して呼び出す場合に使用します。ほとんどの API ではブロッキング API とノンブロッキング API の両方が用意されており、リファレンスガイドでも両方のコード例を扱っています。

以下にユーザー登録でのノンブロッキング API のシーケンス図を示します。

メインスレッドで performRegistration(_:) メソッドを呼び出すと、SDK 内部で作業スレッドが作成され、メソッドはすぐに制御を返します。ネットワーク呼び出しは作業スレッドで実行されるため、この間もユーザーは画面を操作できます。

ネットワーク呼び出しが完了した後、次のイベント処理のタイミングで、メインスレッドによって Swift のクロージャーまたは Objective-C のブロックがコールバックとして呼び出されます。そのため、コールバックにスレッドに関する同期処理は不要です。

実行順序

API 周辺の実行順序は、以下の順番になる点にご注意ください。

  • // Step 1
    user.performRegistration { (user, error) -> Void in
      // Step 3
    }
    // Step 2
  • // Step 1
    [user performRegistrationWithBlock:^(KiiUser *user, NSError *error) {
      // Step 3
    }];
    // Step 2
     

performRegistration(_:) の実行完了後に行いたい処理は、Step 3 の場所に記述します。Step 2 の時点では performRegistration(_:) の処理が終わっていません。たとえば、Step 2 の箇所にユーザー登録後の処理を書いても、その時点では作成処理が始まった直後であるため、多くはエラーとなります。

なお、API を連続で呼び出す処理をコールバックの内部に追加していくと、ネストが深くなってプログラムの見通しが悪くなります。プログラムの可読性を保つには、独自の作業スレッドを作成してブロッキング API を使用する方法などがあります。

結果処理

メソッド呼び出しの結果処理は、クロージャーの内部に記述します。

API を呼び出した際、どのクラスの、どのメソッドを使用すればよいかは、リファレンスガイドのコードサンプルに記載されています。この後のステップで作業例を示します。

ユーザー登録処理での実装をもう一度記載します。

  • // Register the user asynchronously.
    user.performRegistration { (user, error) -> Void in
      if error != nil {
        self.showMessage("Sign up failed", error: error as NSError?)
        return
      }
    
      // Go to the main screen.
      self.performSegue(withIdentifier: "OpenMainPage", sender: nil)
    }
  • // Register the user asynchronously.
    [user performRegistrationWithBlock:^(KiiUser *user, NSError *error) {
      if (error != nil) {
        [self showMessage:@"Sign up failed" error:error];
        return;
      }
    
      // Go to the main screen.
      [self performSegueWithIdentifier:@"OpenMainPage" sender:nil];
    }];

API 呼び出しの結果処理では、まず、例外の有無の判断が必要です。ノンブロッキング API ではネットワークアクセスが行われるため、ネットワークエラーを初めとしたエラーの発生を常に考慮する必要があります。これは、performRegistration(_:) だけに限らず、他のすべてのノンブロッキング API に共通しています。

Hello Kii では以下の処理を行います。

  • 成功時

    変数 error が nil の場合は実行に成功したことを意味します。登録したユーザーでログインしている状態になっています。

    データ一覧画面に遷移するために OpenMainPage セグエによって画面を切り替えます。

    このとき、ユーザーがログインした状態は、SDK 内のスタティック変数に保持されており、データ一覧画面で使用することができます。

  • 失敗時

    error が nil 以外の場合は、SDK 内で発生した例外が error に格納されています。ここでは showMessage(_:error:) メソッドを呼び出して画面表示しています。

    Kii Cloud SDK では、エラーの詳細によって何か処理をしたい場合、errorcode プロパティからエラーコードを取得して分岐したり、userInfo プロパティの description キーからエラーメッセージを取得したりできます。UIViewController+Alert クラスで実装されている showMessage(_:error:) メソッドでは、userInfo プロパティの description キーからエラーメッセージを取得して、画面に表示します。

ログイン

ログイン処理は、呼び出す API が異なるだけで、実装方法はユーザー作成と同じです。

"Log In" ボタンがタップされると、loginButtonPressed(_:) メソッドが実行されます。このメソッドの処理を抜粋すると、以下のようになります。

  • let username = usernameField.text!;
    let password = passwordField.text!;
    
    // Authenticate the user asynchronously.
    KiiUser.authenticate(username, withPassword: password) { (user, error) -> Void in
      if error != nil {
        self.showMessage("Login failed", error: error as NSError?)
        return
      }
    
      // Go to the main screen.
      self.performSegue(withIdentifier: "OpenMainPage", sender: nil)
    }
  • NSString *username = self.usernameField.text;
    NSString *password = self.passwordField.text;
    
    // Authenticate the user asynchronously.
    [KiiUser authenticate:username
             withPassword:password
                 andBlock:^(KiiUser *user, NSError *error) {
      if (error != nil) {
        [self showMessage:@"Login failed" error:error];
        return;
      }
    
      // Go to the main screen.
      [self performSegueWithIdentifier:@"OpenMainPage" sender:nil];
    }];

ユーザー作成と同様に、ユーザー名とパスワードを画面から取得します。

次に、KiiUserauthenticate(_:withPassword:_:) メソッドの引数にそれらを渡してログイン処理を行います。正しい場合、モバイルアプリはログイン状態となります。

authenticate(_:withPassword:_:) メソッドもネットワークアクセスを伴うノンブロッキング API であるため、完了後の処理はクロージャー内に記述します。

  • 成功時

    変数 error が nil の場合は、ログイン成功です。OpenMainPage セグエによってデータ一覧画面に遷移します。

    このとき、ユーザーがログインした状態は、SDK 内のスタティック変数に保持されており、データ一覧画面で使用することができます。

  • 失敗時

    error が nil 以外の場合、ユーザー作成が失敗した場合と同様にエラーメッセージを表示します。

カレントユーザー

前述のように、ログインやユーザー登録が成功したとき、「カレントユーザー」としてログイン中のユーザーが SDK 内で保持されます。このユーザーは次のように取得できます。

  • let user = KiiUser.current()
  • KiiUser *user = [KiiUser currentUser];

取得されるユーザーは、ログインメソッドのコールバックの引数 user と同じユーザーです。

ユーザーを取得すると、そのユーザーのユーザースコープの Bucket にアクセスするなどの様々な操作ができます。

モバイルアプリを終了後、もう一度起動した場合は再ログインの処理が必要です。


次は...

データ一覧画面の処理について説明します。ここではデータの登録や取得を行う API の使用方法などを見ていきます。

データ一覧画面の実装 に移動してください。

より詳しく学びたい方へ