Как использовать завершение Handler Closure с возвратом в 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()
Итак, вот мой вопрос. Как мне сделать так, чтобы этот блокручение окончания могло возвращать 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:
6 ответов
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
}
}
Как вы видите здесь, dataTaskWithRequest:completionHandler:
имеет обработчик завершения без ожидаемого возвращаемого значения.
это означает NSURLSession
экземпляр не ожидает от вас продолжения после вызова этого метода; другими словами: закрытие завершения (или блокировка, если хотите) завершает процедуру здесь.
неясно, почему вы хотите отослать что-либо вызывающей стороне через обработчик завершения.
Обработчик завершения не может ничего вернуть, потому что замыкание, которое вы должны предоставить, должно иметь тип возврата Void, а не AnyObject!.
func dataTaskWithRequest(_ request: NSURLRequest!,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)!) -> NSURLSessionDataTask!
завершениеHandler Закрытие с возвратом в Swift
func checkPassword(pass:String,com:@escaping(Bool)-> String){
if pass.count < 5{
let pass = com(false)
print("Pleas check your password :\(pass)")
}else{
let pass = com(true)
print("You can use this password : \(pass)")
}
}
let password = "test@1"
checkPassword(pass:password ) { (status) in
if status{
print("Strong Password")
}else{
print("weak Password")
}
return password
}
Выход ###
Надежный пароль
Вы можете использовать этот пароль: [email protected]
Я столкнулся с подобной проблемой, когда пытался обновить информацию в центральной БД на основе содержимого, получаемого из CloudKit. Все шаблоны для извлечения CK-данных имеют эти асинхронные обработчики завершения, которые не допускают возврата значения.
Так как я хотел иметь возможность повторно использовать подобный код в разных контекстах, я разделил вызовы CK на их собственный класс и определил протокол делегата, которому я соответствовал базовому классу. В обработчиках завершения я отправлял данные, полученные из вызовов CK, туда, куда я хочу, чтобы они хранились с помощью методов делегата.
Очень просто.
func checkPassword(pass:String,com:@escaping(Bool)-> Void){
if pass.count < 5{
com(false)
}else{
com(true)
}
}
let password = "test@1"
checkPassword(pass:password ) { (status) in
if status{
print("Strong Password")
}else{
print("weak Password")
}
}
Выход###
Надежный пароль