2016-08-20 127 views
5

我正在寫一個庫,所以不使用UIKit,即使在我的iOS應用程序中也有相同的代碼工作,但是當我在命令行中執行時沒有。在PlayGround中,它似乎也在工作。Swift 3,URLSession dataTask completionHandler不叫

由於某種原因,回調沒有被觸發,所以print語句沒有執行。

internal class func post(request: URLRequest, responseCallback: @escaping (Bool, AnyObject?) ->()) { 
    execTask(request: request, taskCallback: { (status, resp) -> Void in 
      responseCallback(status, resp) 
    }) 
} 

internal class func clientURLRequest(url: URL, path: String, method: RequestMethod.RawValue, params: Dictionary<String, Any>? = nil) -> URLRequest { 
    var request = URLRequest(url: url) 
    request.httpMethod = method 
    do { 
     let jsonData = try JSONSerialization.data(withJSONObject: (params! as [String : Any]), options: .prettyPrinted) 

     request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") 
     request.httpBody = jsonData 
    } catch let error as NSError { 
     print(error) 
    } 
    return request 
} 

private class func execTask(request: URLRequest, taskCallback: @escaping (Bool, 
    AnyObject?) ->()) { 

    let session = URLSession(configuration: URLSessionConfiguration.default) 
    print("THIS LINE IS PRINTED") 
    let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in 
     if let data = data { 
      print("THIS ONE IS NOT PRINTED") 
      let json = try? JSONSerialization.jsonObject(with: data, options: []) 
      if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode { 
       taskCallback(true, json as AnyObject?) 
      } else { 
       taskCallback(false, json as AnyObject?) 
      } 
     } 
    }) 
    task.resume() 
} 

編輯 - :我寫一個庫,所以不使用UIKit的,即使是在我的iOS應用程序相同的代碼工作,但是當我在命令行中執行的卻沒有。在PlayGround中,它似乎也在工作。

+0

但如果'在下面的代碼都打印報表不那麼executing'這是不相關的回調...這只是你的'dataTask'方法永遠不會被調用。 – Moritz

+0

請告訴我們你如何調用你的'dataTask'私有方法。 – Moritz

+0

從另一種方法調用它。變量任務正在創建,然後到達resume()。但completionHandler沒有執行。問題本身添加其他代碼。 – xrage

回答

7

我從頭做了一個簡單的應用程序。 (Xcode 8 beta 6/swift 3) 在控制器中,我粘貼了你的代碼。 (加URL創建..) 我看到所有的調試器:

這個人是印花

這一個是打印,TOO

我回來

看起來是這樣幹活。

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let URLString = "https://apple.com" 
     let url = URL(string: URLString) 
     let request = URLRequest(url: url!) 


     ViewController.execTask(request: request) { (ok, obj) in 

      print("I AM BACK") 

     } 

    } 

    private class func execTask(request: URLRequest, taskCallback: @escaping (Bool, 
     AnyObject?) ->()) { 

     let session = URLSession(configuration: URLSessionConfiguration.default) 
     print("THIS LINE IS PRINTED") 
     let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in 
      if let data = data { 
       print("THIS ONE IS PRINTED, TOO") 
       let json = try? JSONSerialization.jsonObject(with: data, options: []) 
       if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode { 
        taskCallback(true, json as AnyObject?) 
       } else { 
        taskCallback(false, json as AnyObject?) 
       } 
      } 
     }) 
     task.resume() 
    } 

} 
+0

我正在寫一個命令行實用程序,所以不使用UIKit,即使在我的應用程序相同的代碼作品,但是當我在命令行中執行不。在PlayGround中,它似乎也在工作。 – xrage

2

是否在此處提出了更改,現在可以使用。

Using NSURLSession from a Swift command line program

var sema = DispatchSemaphore(value: 0) 

private func execTask(request: URLRequest, taskCallback: @escaping (Bool, 
    AnyObject?) ->()) { 

    let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil) 

    session.dataTask(with: request) {(data, response, error) -> Void in 
     if let data = data { 
      let json = try? JSONSerialization.jsonObject(with: data, options: []) 
      if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode { 
       taskCallback(true, json as AnyObject?) 
      } else { 
       taskCallback(false, json as AnyObject?) 
      } 
     } 
    }.resume() 
    sema.wait() 
} 
+0

非常好的taskCallBacks解釋。 – Juanjo

1
let dataTask = session.dataTask(with: request, completionHandler: {data, response,error -> Void in 
    print("Request : \(response)") 

    let res = response as! HTTPURLResponse 

    print("Status Code : \(res.statusCode)") 

    let strResponse = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) 
    print("Response String :\(strResponse)") 
    }) 
dataTask.resume() 
0

雨燕3.0

下面的代碼只需複製到您的視圖控制器。

@IBAction func btnNewApplicationPressed (_ sender: UIButton) { 
     callWebService() 
} 

func callWebService() { 
    // Show MBProgressHUD Here 
    var config        :URLSessionConfiguration! 
    var urlSession       :URLSession! 

    config = URLSessionConfiguration.default 
    urlSession = URLSession(configuration: config) 

    // MARK:- HeaderField 
    let HTTPHeaderField_ContentType   = "Content-Type" 

    // MARK:- ContentType 
    let ContentType_ApplicationJson   = "application/json" 

    //MARK: HTTPMethod 
    let HTTPMethod_Get      = "GET" 

    let callURL = URL.init(string: "https://itunes.apple.com/in/rss/newapplications/limit=10/json") 

    var request = URLRequest.init(url: callURL!) 

    request.timeoutInterval = 60.0 // TimeoutInterval in Second 
    request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData 
    request.addValue(ContentType_ApplicationJson, forHTTPHeaderField: HTTPHeaderField_ContentType) 
    request.httpMethod = HTTPMethod_Get 

    let dataTask = urlSession.dataTask(with: request) { (data,response,error) in 
     if error != nil{ 
      return 
     } 
     do { 
      let resultJson = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] 
      print("Result",resultJson!) 
     } catch { 
      print("Error -> \(error)") 
     } 
    } 

    dataTask.resume() 
} 
+3

考慮解釋你的答案。不鼓勵代碼的答案。 – ADyson

+0

試過這個答案,沒有工作http://stackoverflow.com/questions/42481033/swifthttp-library-not-making-the-http-call#42481033 – Siddharth

+0

首先,任務不在主線程中。因此,UI中的任何內容都需要調用DispatchQueue.main.async(execute:{code}),然後您需要添加回調,否則該回調將立即返回。這是Swift 3. – Juanjo

1

我知道它遲到的答案,但如果你沒有找出問題或在其他地方得到問題,讓我們試試這個。

您需要將方法範圍外的會話變量保存(使其成爲實例變量)。由於您在函數範圍內在本地定義了它。它的get可以在調用完成之前釋放處理器,記住完成處理程序不能保留你的會話對象,並且在運行循環執行後,垃圾回收器將釋放會話對象。我們需要保留這些對象,每當我們想從代表或完成處理再打..

self.session = URLSession(configuration: URLSessionConfiguration.default) 
+0

非常有幫助,感謝分享! –

相關問題