2017-03-09 8 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

내가 그 '완료 (NSArray를 (객체를 생각한다 : teamResult), Int (teamInput.text!)!)'는'print (jsonResult)'가있는 곳으로 가야합니다. 지금은 데이터 작업을 시작한 다음 완료 핸들러를 (아마도)'nil'을 사용하여 즉시 호출합니다. 데이터 타스크 핸들러 내에서 (인쇄 메소드 중 하나에서) 중단 점이 있으면 중단 점에 충돌합니까? – keithbhunter

+1

Alamofire를 살펴보고이 프로젝트에서 가능한 경우 사용하는 것이 좋습니다. 이렇게 코드를 작성하는 것이 훨씬 쉽습니다. –

+0

예, 처리기를 데이터 작업으로 이동하면 아름답게 작동하는 것 같습니다. 정말 고맙습니다! –

답변

3

코드가 잘못 구성되었습니다.

URLSession은 비동기 적으로 실행되는 작업을 만듭니다. 작업을 설정하고 완료 블록을 전달하거나 대리인을 설정합니다.

task.resume() 호출은 네트워크 다운로드가 완료되기 바로 전에 즉시 반환됩니다.

작업이 완료되면 시스템이 완료 처리기 (또는 대리인 스타일을 사용하는 경우 대리인)를 호출합니다.

URLSessions의 완료 핸들러와 델리게이트 호출은 백그라운드 스레드에서 수행됩니다. 작업 완료에 대한 응답으로 UIKit 호출을 수행하는 경우 주 스레드에서 수행해야합니다.

@keithbhunter는 그의 의견에서 완성 처리기에 대한 호출을 작업 완료 핸들러에 넣어야한다고 말했습니다. teamInput.text 당신의 힘 랩핑 해제가 매우 취약

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() 
} 

주 및 teamInput.text이 전무 경우 충돌합니다 : 당신이 메인 스레드에 대한 호출에 그 전체 완료 핸들러 호출을 래핑 경우는 아마 가장 안전합니다 또는 Int로 변환 할 수없는 경우.

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

및 옵션을 전달 호출 :

let value: Int? = teamInput.text != nil ? Int(teamInput.text!) : nil 
completion(NSArray(object: teamResult), value) 
을 당신은 데이터와 int 값 당신은 teamInput.text에서 돌아 오기 모두에 대해 선택적 항목을 적용하려면 완료 핸들러를 작성하는 오프 더 나은 것
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-labrapping은 위험합니다. 내 대답보기 ... –

0

이 시도 :

이 나를 위해 시간을 많이 도움이되었습니다
let urlString = "www.yoururl.com" 
let url = URL(string: string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)