進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

REST API による Salesforce データへのアクセス

学習の目的

この単元を完了すると、次のことができるようになります。

  • RestClient インターフェースを使用して REST 要求を発行する。
  • Salesforce から REST 応答を受信する。
  • Mobile SDK を使用して REST 応答を処理する。

REST 要求の送信

RootViewController クラスで、Mobile SDK の REST API クラスのしくみを少しだけ見ることができます。これらのオブジェクトの使用方法を詳しく見てみましょう。

RestClient オブジェクトと RestRequest オブジェクトの使用

Mobile SDK REST API を使用して Salesforce データにアクセスするには、Salesforce に要求を送信してアプリケーションで応答を受信します。では、RootViewController はネットワーク要求をどのように送信するのでしょうか?

loadView() メソッドで実施される標準の「送信要求」シーケンスは次のようになります。
  1. RestRequest インスタンスを作成して初期化します。RestClient は、この目的で数多くのファクトリメソッドを用意しています。この例では SOQL クエリ要求を作成していますが、目的に合わせて任意の RestClient メソッドを選択できます。
  2. 要求オブジェクトを Salesforce に送信します。RestClient は、現在のユーザのログイン情報を使用して自動的に要求を認証します。
では、コードを詳しく見てみましょう。
  1. Xcode で、RootViewController.swift ファイルを開きます。
  2. loadView() メソッドを検索します。実装は、次のようになります。
    override func loadView() {
        super.loadView()
        self.title = "Mobile SDK Sample App"
        let request = RestClient.shared.request(forQuery: "SELECT Name FROM User LIMIT 10")        
        RestClient.shared.send(request: request, onFailure: { (error, urlResponse) in
            SalesforceLogger.d(type(of:self), message:"Error invoking: \(request)")
        }) { [weak self] (response, urlResponse) in
            
            guard let strongSelf = self,
                let jsonResponse = response as? Dictionary<String,Any>,
                let result = jsonResponse ["records"] as? [Dictionary<String,Any>]  else {
                    return
            }
            
            SalesforceLogger.d(type(of:strongSelf),message:"Invoked: \(request)")
            
            DispatchQueue.main.async {
                strongSelf.dataRows = result
                strongSelf.tableView.reloadData()
            }
        }
    }
スーパークラスメソッドをコールしてビュータイトルを設定した後、このメソッドは REST 要求を作成して送信します。このために、次の 2 つを使用します。
  • RestClient 共有インスタンスは、ネットワーク経由で Salesforce に送信される要求オブジェクトを生成する。
  • 生成された RestRequest オブジェクトには、所定の SOQL 文字列に基づいて実行された REST API 要求が含まれる。

REST 応答を処理するために、RootViewControllersend(request:onFailure:onSuccess:) メソッドの最後の 2 つのパラメータを使用します。このメソッドでは、失敗を処理するクロージャと成功を処理する別のクロージャを提供します。テンプレートコードは、失敗ブロックを onFailure: 引数として追加し、成功ブロックは onSuccess: 引数と思うでしょうが、そうではありません。この想定外のコードでは、「トレイリングクロージャ構文」という Swift 機能を使用します。この機能を使用すると、関数の最後の引数がクロージャの場合、そのパラメータを省略できます。代わりに、コールの閉じ括弧の直後にクロージャを追加します。トレイリングクロージャによって構文が簡潔になり、最後のクロージャをコールの予想される結果として区別します。

このようにして、要求を送信して、成功クロージャと失敗クロージャを示す応答を処理します。ここで疑問が浮かぶかもしれません。たとえば、「この行は何を意味するのか?」
{[weak self] (response, urlResponse) in ...
「他にオプションはないのか?」といった疑問です。続けましょう。
メモ

メモ

RestClient は、すべての REST サービスへのエントリポイントとなるものです。RestClient には常に共有インスタンス RestClient.shared() を介してアクセスします。

REST 応答の処理

Salesforce からデータを受信して使用するには、非同期ネットワークコールバックをインターセプトする機能が必要です。Mobile SDK は、このタスクの次の 2 つのオプションを定義します。
RestClient send(request:onFailure:onSuccess:) メソッド
send 関数をコールするときに、失敗クロージャと成功クロージャを渡します。Salesforce がこのメソッドコールに応答コールバックを送信します。
RestClientDelegate プロトコル
成功応答と失敗応答を受信する 4 つのコールバック関数を定義します。アプリケーションが REST 要求を送信すると、このプロトコルをサーバの応答のターゲットとして実装するクラスが指定されます。

Objective-C ではおそらく、インラインブロックコールバックではなく SFRestDelegate プロトコルを使用するほうが明快でしょう。これは RestClientDelegate の Objective-C 版です。ただし、Swift アプリケーションでは、トレイリングクロージャ構文を使用するメリットがあり、上記のプロトコルよりよい解決策となります。この手法を使用すると、要求の生成から応答の処理まで読み取りやすい自然なフローになります。インラインクロージャはまた、RestClientDelegate プロトコルよりもコーディングが簡単です。

RestClient send(request:onFailure:onSuccess:) メソッドの使用

では、Swift テンプレートアプリケーションで send(request:onFailure:onSuccess:) メソッドをコーディングする方法を詳しく見ていきましょう。

  1. RootViewController テンプレートクラスは Mobile SDK REST API を使用して SOQL 要求を使用します。
    let request = RestClient.shared.request(forQuery: "SELECT Name FROM User LIMIT 10")
  2. 次の行で、要求を Salesforce に送信する send メソッドをコールします。このメソッドは onFailure 引数と onSuccess 引数にクロージャを使用します。次に例を示します。
    let request = RestClient.shared.request(forQuery: "SELECT Name FROM User LIMIT 10")
    RestClient.shared.send(request: request, onFailure: { },
        onSuccess: { })
  3. 失敗の場合は、Mobile SDK が onFailure クロージャに次の値を送信します。
    • NSError 種別の応答オブジェクト (error)
    • NSURLResponse 種別のネットワーク応答 (urlResponse)
    このアプリケーションはエラーメッセージをデバッガに記録して次に進みます。
    let request = RestClient.shared.request(forQuery: "SELECT Name FROM User LIMIT 10")
    RestClient.shared.send(request: request, onFailure: { (error, urlResponse) in
        SalesforceLogger.d(type(of:self), message:"Error invoking: \(request)")
    },
        onSuccess: { })
    onFailure: クロージャがサーバのコールバックを受け取ると、send メソッドが onSuccess: クロージャをスキップして戻ります。
onSuccess クロージャがコールバックを受信した場合は、アプリケーションがそのロジックを展開できます。前述のとおり、トレイリングクロージャ構文を使用すると send(request:onFailure:onSuccess:) メソッドコールに onSuccess 引数が不要になります。代わりに、メソッドの閉じ括弧の直後にクロージャを追加します。
let request = RestClient.shared.request(forQuery: "SELECT Name FROM User LIMIT 10")
RestClient.shared.send(request: request, onFailure: { (error, urlResponse) in
    SalesforceLogger.d(type(of:self), message:"Error invoking: \(request)")
}){ 
    // We closed the send call after the onError: closure
    // and, on the same line, added the opening brace for an 
    // anonymous trailing closure to handle the success logic.
}
これで、成功クロージャを見つけやすくなります。要求に成功すると、サーバから次の値が送信されます。
  • Dictionary<String, Any> 種別の応答オブジェクト (response)
  • NSURLResponse 種別のネットワーク応答 (urlResponse)
これらの値はクロージャのキャプチャリストでキャプチャします。
RestClient.shared.send(request: request, onFailure: { (error, urlResponse) in
            SalesforceLogger.d(type(of:self), message:"Error invoking: \(request)")
}) { [weak self] (response, urlResponse) in
    
}
トレイリング成功クロージャで、この応答をアプリケーションのニーズに適用させることができます。暗黙の self 参照に [weak self] が使用されています。REST 応答は非同期に届くため、成功クロージャを定義するクラスがコールされた時点でまだメモリにあるかどうかがわかりません。不要な保持サイクルを回避するために、暗黙の self 参照を weak に変更します。weak 参照を確信もって使用するには、クロージャ内を調べ、使用続ける前に self 参照が nil 以外であることを確認します。たとえば、応答のラッピングを解除しようとするときに guard ステートメントを使用できます。以下は、forceius Swift テンプレートの成功ハンドラです。
}) { [weak self] (response, urlResponse) in
            
    guard let strongSelf = self,  // Creates a strong ref by setting 
                                  // weak self (possibly nil) to a constant
        // Parse the entire response into a dictionary
        let jsonResponse = response as? Dictionary<String,Any>,
        // Extract the Salesforce records embedded in the response. 
        // If anything fails, get out of here with a return.
        let result = jsonResponse ["records"] as? [Dictionary<String,Any>]  else {
            return
    }
    // Everything is good with strongSelf and the response.
    // Do what you like with the resulting records.
    SalesforceLogger.d(type(of:strongSelf),message:"Invoked: \(request)")

    DispatchQueue.main.async {
        strongSelf.dataRows = result
        strongSelf.tableView.reloadData()
    }
}

RestClientDelegate プロトコルの使用

RestClientDelegate は、コードを明快にするほか、失敗のカテゴリを解析して、失敗応答をカテゴリ固有のハンドラに送信します。クラスが RestClientDelegate プロトコルを採用した場合は、4 つの応答ハンドラ関数を実装します。

  • request(_:didLoadResponse:) — 要求が処理されました。代理オブジェクトは JSON 形式の応答を受信します。このコールバックは成功を示します。send(request:onFailure:onSuccess:) メソッドの成功クロージャに配置したものと同じコードが含まれます。
  • request(_:didFailLoadWithError:) — 要求を処理できませんでした。代理オブジェクトはエラーメッセージを受信します。send(request:onFailure:onSuccess:) メソッドでは、onFailure クロージャでこのエラーを処理します。
  • requestDidCancelLoad(_:) — システム管理者による操作、ネットワーク障害、他の予期しないイベントなど、外部要因により要求がキャンセルされました。代理オブジェクトは戻り値を受信しません。send(request:onFailure:onSuccess:) メソッドでは、onFailure クロージャでこの失敗を処理します。
  • requestDidTimeout(_:) — Salesforce サーバが時間内に応答しませんでした。代理オブジェクトは戻り値を受信しません。send(request:onFailure:onSuccess:) メソッドでは、onFailure クロージャでこの失敗を処理します。

Mobile SDK は成功応答を request(_:didLoadResponse:) コールバックに配信します。ネットワーク応答の復号化方法についての心配はもう不要です。デフォルトで、Mobile SDK は応答を辞書オブジェクト内の読みやすい JSON 形式にします。その辞書には、「レコード」キーが含まれます。このキーの値が、Salesforce レコードの配列になります。エラー、キャンセル、タイムアウトの条件はそれぞれ独自のハンドラで処理されるため、失敗の種類に基づいて特定のアクションを簡単に実装できます。

これで、ひととおり終わりました。ここでは、アプリケーションを初期化し、ユーザをログインし、REST 要求を発行して、REST 応答を表示しました。現在、アプリケーションは他に何をすればよいかわからないため、停止しています。次は、左スワイプによる削除のようなユーザ操作のサポートを追加して、アプリケーションをもう少し堅牢にしましょう。

retargeting