Как использовать завершение закрытия Handler с возвратом в Swift?
Я пытаюсь использовать RESTful API, который возвращает некоторые json-данные. Я хочу инкапсулировать код, который создает HTTP-запрос, и устанавливает заголовки в свой собственный метод, поэтому я могу вызвать его, введя строчку url, а затем вернуть метод JSON-объекту.
В следующем фрагменте кода я уже создал объект запроса и задал заголовки, и я вызываю эту переменную "req". Я не объявлял никаких объектов с именем data, response или error. У меня есть следующий код, который правильно выводит объект JSON
let sesh = NSURLSession.sharedSession()
let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) in
var jsonError : NSError?
let jsonBlob = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError)
println(jsonBlob)
});
dataTask.resume()
Итак, вот мой вопрос. Как мне сделать так, чтобы этот блок completHandler смог вернуть jsonBlob, который имеет тип "AnyObject!"? Если я немного модифицирую код, чтобы быть следующим:
let sesh = NSURLSession.sharedSession()
let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) -> AnyObject! in
var jsonError : NSError?
let jsonBlob : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError)
return jsonBlob
});
dataTask.resume()
то программа не будет компилироваться как вызов dataTaskWithRequest: completeHandler дает предупреждение компилятора:
Could not find an overload for 'dataTaskWithRequest' that accepts the supplied arguments
Я не понимаю этого. Я использую правильный синтаксис для возврата закрытий, как указано на этой странице Swift Docs:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
Ответы
Ответ 1
func getSomething(callback: (Array<AnyObject>) -> ()) {
var dataTask = NSURLSessionDataTask()
dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
if (error == nil) {
var callbackArray = Array<MyObject>()
let responseDict = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary
let response = responseDict.objectForKey("response_key") as NSDictionary
let array = response.objectForKey("array_key") as NSArray
for item: AnyObject in array {
var arrayItem = MyObject(dict: item as NSDictionary)
callbackArray.append(arrayItem)
}
callback(callbackArray)
} else {
// handle an error
}
}
dataTask.resume()
}
Тогда вы можете сделать что-то вроде:
getSomething() { (response) in
if let responseArray = response as? Array<MyObject> {
self.somethings = responseArray
}
}
Ответ 2
как вы видите здесь, dataTaskWithRequest:completionHandler:
имеет обработчик завершения без ожидаемого возвращаемого значения.
![completion handler's interface]()
это означает, что экземпляр NSURLSession
не ожидает от вас значения для продолжения после вызова этого метода; другими словами: завершение закрытия (или блок, если хотите) завершает процедуру здесь.
неясно, почему вы хотите отправить что-либо вызывающему через обработчик завершения.
Ответ 3
Обработчик завершения не может ничего вернуть, потому что закрытие, которое вы должны поставить, должно иметь тип возврата Void, а не AnyObject!.
func dataTaskWithRequest(_ request: NSURLRequest!,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)!) -> NSURLSessionDataTask!
Ответ 4
Я столкнулся с подобной проблемой при попытке обновить информацию в центральной базе данных на основе контента, который вытаскивал из CloudKit. Шаблоны для вытягивания данных CK имеют эти асинхронные обработчики завершения, которые не позволяют возвращать значение.
Поскольку я хотел иметь возможность повторно использовать похожий код в разных контекстах, я отделил вызовы CK в свой собственный класс и определил протокол делегата, с которым я соответствовал базовому классу. В обработчиках завершения я отправил данные, полученные с CK, обратно туда, где я хочу, чтобы они были сохранены с помощью методов делегирования.
Легкий peasy.