2016-08-20 2 views
5

Я пишу библиотеку, поэтому не использую UIKit, Даже в моем приложении iOS один и тот же код работает, но когда я выполняю в командной строке, это не так. В PlayGround тоже кажется работающим.Swift 3, URLSession dataTask completeHandler не вызван

По какой-то причине обратный вызов не запускается, поэтому заявления печати не выполняются.

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(). но completeHandler не выполняется. Добавление другого кода в вопрос. – xrage

ответ

7

Я сделал простое приложение с нуля. (Xcode 8 beta 6/swift 3) В контроллере я вставил ваш код. (Создание плюс URL ..) я вижу все в отладчике:

ЭТИ распечатывается

ЭТИ распечатываются, ТОО

Я вернулся

так кажется, работает.

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

Очень приятно объяснение задачиCallBacks. – 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

Swift 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

Прежде всего задача не в основном потоке. Итак, что-нибудь в пользовательском интерфейсе должно вызвать DispatchQueue.main.async (выполнить: {code}), а затем вам нужно добавить обратный вызов или вызов немедленно вернется. Это для Swift 3. – Juanjo

1

Я знаю его опоздание на ответ, но если вы не выяснили проблему или не получили проблемы в других местах, попробуйте это.

Вам необходимо сохранить переменную сеанса вне области действия (сделайте ее переменной экземпляра). Поскольку вы определили его локально в области функций. Его можно освободить до того, как обработчик завершения может быть вызван, помните, что обработчик завершения не может сохранить ваш объект сеанса, и после выполнения цикла выполнения сборщик мусора отключит ваш объект сеанса. Нам нужно сохранить такие объекты, когда мы хотим, чтобы перезвонить делегат или обработчик завершения ..

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

очень полезно, спасибо за обмен! –

Смежные вопросы