2017-12-29 21 views
0

私はXcodeの遊び場ファイルで働いていたコードの一部を使用して、ローカルサーバーからいくつかのデータを取得しようとしています:スウィフト:URLSession完了ハンドラ

 URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) -> Void in 


      if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary { 
       friend_ids = (jsonObj!.value(forKey: "friends") as? NSArray)! 
      } 

     }).resume() 

return friend_ids 

はこのトピックに関するいくつかの同様の質問を読んでたので、私はURLSessionは非同期で実行されるため、サーバーからデータを取得する前に関数がnil値を返すことに注意してください。私はまた、完了ハンドラを使用してデータが実際に取得される前に確実に取得できることを理解していると思っていますが、残念ながら実際の実装方法を理解できませんでした。変数が返される前にサーバから取得されることを保証するために、この単純な例で補完ハンドラをどのように使用するかを誰かに教えてもらえますか?

ありがとうございました!

答えて

1

非同期作業を行っている関数がある場合、その非同期作業の結果を表す戻り値を持つことはできません(関数の戻り値は即時です)。したがって、非同期作業を行う関数は、期待される結果を受け取り、非同期作業が完了したときに呼び出されるパラメータとしてクロージャをとる必要があります。したがって、あなたのコードの場合:

func getFriendIds(completion: @escaping (NSArray) ->()) { 
    URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) -> Void in 
     if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary { 
      friend_ids = (jsonObj!.value(forKey: "friends") as? NSArray)! 
      completion(friend_ids) // Here's where we call the completion handler with the result once we have it 
     } 
    }).resume() 
} 

//USAGE: 

getFriendIds(completion:{ 
    array in 
    print(array) // Or do something else with the result 
}) 
+0

私はこれを試しましたが、完了ブロックを無視しているようです。一行ずつ進むと、URLSession行から二度目のレジューム行に移動してから、関数を終了します。 – jasperthedog

+0

取得しようとしているURLは何ですか?リクエストがタイムアウトしたか、失敗している可能性があります。特に、URLがhttp://で、https://でない場合は、例外を作成しない限り、iOS App Transport Securityによってブロックされます。すべての情報をコンソールに出力しますか? –

関連する問題