0

一般に、ネットワーク用のクラスを実装する必要があります。これは、URL を受け取り、データを提供するクラスです。これはすべて、余分なロジック コントローラーを獲得しないために行われます。最初にビューを作成したときに、データが来ないという問題が発生しました。それはネットワーククラスです:

private static var dataTask: NSURLSessionDataTask?

private static var dataJSON: NSData?

private static var sessionConfig: NSURLSessionConfiguration = {
    var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    configuration.allowsCellularAccess = false
    configuration.HTTPMaximumConnectionsPerHost = 2
    configuration.HTTPAdditionalHeaders = ["Accept": "application/json"]
    configuration.timeoutIntervalForRequest = 30.0
    configuration.timeoutIntervalForResource = 60.0
    return configuration
}()


static func getListObjectsBy(url: String?) -> NSData? {
    let session = NSURLSession(configuration: sessionConfig)
    log.debug("DataTask start")
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in
        log.debug("if error = error")
        if let error = error {
            print(error.localizedDescription)
        } else if let httpResponse = response as? NSHTTPURLResponse {
            log.debug("if httpResponse")
            if httpResponse.statusCode == 200 {
                dataJSON = data
            } else {
                print("Bad request")
            }
        }
    }
    dataTask?.resume()
    log.debug("DataTask Resume")
    return dataJSON
}

私のメインコントローラーのメソッドviewDidLoad:

let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5")
print(String(response))

私のログによると、そのデータは nil を返します。注、私は SWRevealViewController の助けを借りてコントローラーを切り替えています。メインView Controllerをリロードすると、データが返されます。私は何をしますか?

ここに画像の説明を入力

4

1 に答える 1

1

これが非同期呼び出しであると誤解しているようです。

static func getListObjectsBy(url: String?) -> NSData? {
    let session = NSURLSession(configuration: sessionConfig)
    log.debug("DataTask start")
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in
        // Everything in this block is happening on a separate thread.
        log.debug("if error = error")
        if let error = error {
            print(error.localizedDescription)
        } else if let httpResponse = response as? NSHTTPURLResponse {
            log.debug("if httpResponse")
            if httpResponse.statusCode == 200 {
                // this won't happen until the data comes back from the remote call.
                dataJSON = data
            } else {
                print("Bad request")
            }
        }
    }
    // This code here does not wait for the response from the remote.
    // The call to the remote is sent then this code 
    // is immediately executed WITHOUT WAITING
    dataTask?.resume()
    log.debug("DataTask Resume")
    // dataJSON will be nil until the remote answers.
    return dataJSON
}

これを行う場合:

let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5")
print(String(response))

リモートはまだ応答していないため、nil が返されます。

次の質問は、「これについてどうすればよいですか?」かもしれません。あなたがしていることをすべて知らなければ、答えは明らかではありません。

スレッド

複数の実行スレッドは、同時に実行される 2 つのプログラムのようなものです。2 人の人が同時に 2 つの異なるタスクに取り組んでいると考えてください。インターフェイスの応答性を維持するために、iOS は画面の更新に 1 つの実行スレッドを使用します。時間がかかるプロセスを実行する必要がある場合、それが完了するまで画面を待機させたくありません。あるリモート システムからデータをフェッチする必要があり、そのリモート システムが遅いとします。応答が返されるまで、デバイスはそこにフリーズしたままになります。これを回避するために、リモート システムへの呼び出しなどのアクティビティは別のスレッドで実行されます。要求はオペレーティング システム自体に送信され、オペレーティング システムは操作が完了したときにコールバックするように指示されます。

これがここで起こっていることです。
オペレーティング システムに送信する要求を設定します。

dataTask = session.dataTaskWithURL(NSURL(string: url!)!)

作業を開始するようにオペレーティング システムに指示します。

dataTask?.resume()

このブロックは、クロージャとも呼ばれるコールバックです。リモート呼び出しが完了すると、iOS はこのコードを実行します。

dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { 
    // Closure starts here
    // Gets called when the remote has sent a response.
    (data, response, error) in
    // Everything in this block is happening on a separate thread.
    log.debug("if error = error")
    etc
}

これは、出力を印刷する前に、応答が返ってくるまで待たなければならないことを意味します。これを行うには、関数でクロージャーを使用できます。

public typealias CompletionHandler = (data: NSData?, error: NSError?) -> Void

static func getListObjectsBy(url: String?, completion: CompletionHandler) {
    let session = NSURLSession(configuration: sessionConfig)
    log.debug("DataTask start")
    dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { 
        (data, response, error) in
        // Everything in this block is happening on a separate thread.
        log.debug("if error = error")
        if let error = error {
            print(error.localizedDescription)
        } else if let httpResponse = response as? NSHTTPURLResponse {
            log.debug("if httpResponse")
            if httpResponse.statusCode == 200 {
                // this won't happen until the data comes back from the remote call.
            } else {
                print("Bad request")
            }
        }
        // Call your closure
        completion(data, error)
    }
    // This code here does not wait for the response from the remote.
    // The call to the remote is sent then this code 
    // is immediately executed WITHOUT WAITING
    dataTask?.resume()
    log.debug("DataTask Resume")
}

呼び出しコードでは、次のようにします。

Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") {
    (data, error)  in
    if let data == data {
        print(data)
    }
}
于 2016-03-19T17:35:18.177 に答える