2017-03-09 11 views
4

私はthis postと非常によく似た問題を抱えていますが、私はその答えを完全に理解していません。私は補完ハンドラを作成しましたが、期待どおりに機能していないようです。スウィフトURLセッションとURLリクエストが機能しない

func updateTeam(teamID: Int) { 
    startConnection {NSArray, Int in 
     //Do things with NSArray 
    } 
} 

func startConnection(completion: (NSArray, Int) -> Void) { 
    let url = URL(string: "http://www.example.com/path") 
    var request : URLRequest = URLRequest(url: url!) 
    request.httpMethod = "POST" 
    let postString = "a=\(Int(teamInput.text!)!)" 
    request.httpBody = postString.data(using: .utf8) 

    let dataTask = URLSession.shared.dataTask(with: request) { 
     data,response,error in 
     print("anything") 
     do { 
      if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary { 
       self.teamResult = jsonResult 
       print(jsonResult) 
      } 
     } catch let error as NSError { 
      print(error.localizedDescription) 
     } 

    } 
    dataTask.resume() 

    completion(NSArray(object: teamResult), Int(teamInput.text!)!) 
} 

dataTask文の中では何も実行していないようにみえ、または私はデータが結果を使用しようとする前に、少なくとも、それが完了しません。この補完ハンドラで何が問題になっていますか?

ありがとうございます!

+0

の多くを助けた

let urlString = "www.yoururl.com" let url = URL(string: string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) 

をteamResult)、Int(teamInput.text!)!) 'は' print(jsonResult) 'を持つ場所になければなりません。今のように、データタスクを開始してすぐに(おそらく) 'nil'で補完ハンドラを呼び出します。データ・ハンドラ・ハンドラの中で(印刷メソッドのいずれかで)ブレークポイントを設定すると、ブレークポイントがヒットしますか? – keithbhunter

+1

Alamofireを検索して、このプロジェクトのために使用できる場合は、このようなコードを書くことをお勧めします。 –

+0

はい、ハンドラをデータタスクに移動すると美しく動作しました。どうもありがとうございます! –

答えて

3

コードが正しく構成されていません。

URLSessionは、非同期に実行されるタスクを作成します。タスクを設定し、完了ブロックを渡すか、デリゲートを設定します。

task.resume()呼び出しは、ネットワークのダウンロードが完了する前にすぐに戻ります。

タスクが完了すると、システムは完了ハンドラ(またはデリゲートスタイルを使用する場合は代理人)を呼び出します。

URLSessionsの完了ハンドラとデリゲートコールは、バックグラウンドスレッドで行われることに注意してください。タスクが完了したことに応答してUIKit呼び出しを行う場合は、メインスレッドで実行する必要があります。

@keithbhunterは、彼のコメントで、完了ハンドラの呼び出しをタスクの完了ハンドラの中に置く必要があると述べています。 teamInput.textのあなたの力アンラップは非常に脆弱であり、そしてteamInput.textがnilである場合にクラッシュすること

func startConnection(completion: (NSArray, Int) -> Void) { 
    let url = URL(string: "http://www.example.com/path") 
    var request : URLRequest = URLRequest(url: url!) 
    request.httpMethod = "POST" 
    let postString = "a=\(Int(teamInput.text!)!)" 
    request.httpBody = postString.data(using: .utf8) 

    let dataTask = URLSession.shared.dataTask(with: request) { 
     data,response,error in 
     print("anything") 
     do { 
      if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary { 
       self.teamResult = jsonResult 
       print(jsonResult) 
       //Use GCD to invoke the completion handler on the main thread 
       DispatchQueue.main.async() { 
        completion(NSArray(object: teamResult), Int(teamInput.text!)!) 
       } 
      } 
     } catch let error as NSError { 
      print(error.localizedDescription) 
     } 
    } 
    dataTask.resume() 
} 

注:あなたがメインスレッドへの呼び出しでその全体の完了ハンドラの呼び出しをラップする場合、それはおそらく最も安全なのですまたはIntに変換できない場合

func startConnection(completion: (NSArray?, Int?) -> Void) { 

とオプションを渡し、それを呼び出す:あなたは、あなたが戻ってteamInput.textから取得したデータと、int型の値の両方のためのoptionalsを取るためにあなたの完了ハンドラを作成するためにオフにはるかに良いと思います

let value: Int? = teamInput.text != nil ? Int(teamInput.text!) : nil 
completion(NSArray(object: teamResult), value) 
2

私は閉鎖時のエラーも処理する必要があると思います。

func updateTeam(teamID: Int) { 
    startConnection {array, teamId, error in 
     // Do things with NSArray or handle error 
    } 
} 

func startConnection(completion: @escaping (NSArray?, Int, Error?) -> Void) { 
    let url = URL(string: "http://www.example.com/path") 
    var request : URLRequest = URLRequest(url: url!) 
    request.httpMethod = "POST" 
    let postString = "a=\(Int(teamInput.text!)!)" 
    request.httpBody = postString.data(using: .utf8) 

    let dataTask = URLSession.shared.dataTask(with: request) { 
     data,response,error in 
     print("anything") 
     do { 
      if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary { 
       self.teamResult = jsonResult 
       print(jsonResult) 
       DispatchQueue.main.async() { 
        completion(NSArray(object: self.teamResult), Int(teamInput.text!)!, nil) 
       } 
     } catch let error as NSError { 
      print(error.localizedDescription) 
      DispatchQueue.main.async() { 
       completion(nil, Int(teamInput.text!)!, error) 
      } 
     } 

    } 
    dataTask.resume() 
} 
+0

OPのforce-unwrappingというteamInputも危険です。私の答えを見て... –

0

このお試しください::これは私のために私は `完了(NSArrayの(オブジェクトと思い倍

関連する問題