Mar*_*ers 83 rest asynchronous ios swift
我在Swift项目中创建了一个实用程序类来处理所有REST请求和响应.我已经构建了一个简单的REST API,因此我可以测试我的代码.我创建了一个需要返回NSArray的类方法,但由于API调用是异步的,我需要从异步调用中的方法返回.问题是异步返回void.如果我在Node中执行此操作,我会使用JS承诺,但我无法找到适用于Swift的解决方案.
import Foundation
class Bookshop {
class func getGenres() -> NSArray {
println("Hello inside getGenres")
let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
println(urlPath)
let url: NSURL = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
var resultsArray:NSArray!
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error) {
println(error.localizedDescription)
}
var err: NSError?
var options:NSJSONReadingOptions = NSJSONReadingOptions.MutableContainers
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: options, error: &err) as NSDictionary
if(err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//NSLog("jsonResults %@", jsonResult)
let results: NSArray = jsonResult["genres"] as NSArray
NSLog("jsonResults %@", results)
resultsArray = results
return resultsArray // error [anyObject] is not a subType of 'Void'
})
task.resume()
//return "Hello World!"
// I want to return the NSArray...
}
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*tyy 86
您可以传递回调,并在异步调用中调用回调
就像是:
class func getGenres(completionHandler: (genres: NSArray) -> ()) {
...
let task = session.dataTaskWithURL(url) {
data, response, error in
...
resultsArray = results
completionHandler(genres: resultsArray)
}
...
task.resume()
}
Run Code Online (Sandbox Code Playgroud)
然后调用此方法:
override func viewDidLoad() {
Bookshop.getGenres {
genres in
println("View Controller: \(genres)")
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*ier 11
Swiftz已经提供了Future,这是Promise的基本构建块.未来是一个不能失败的承诺(这里的所有术语都基于Scala解释,其中Promise是Monad).
https://github.com/maxpow4h/swiftz/blob/master/swiftz/Future.swift
希望最终会扩展到完整的Scala风格的Promise(我可能会在某个时候自己编写;我相信其他的PR会受到欢迎;并且Future已经到位并不困难).
在你的特殊情况下,我可能会创建一个Result<[Book]>(基于Alexandros Salazar的版本Result).然后您的方法签名将是:
class func fetchGenres() -> Future<Result<[Book]>> {
Run Code Online (Sandbox Code Playgroud)
笔记
get在Swift中使用函数前缀.它将破坏与ObjC的某些互操作性.Book在将结果作为a返回之前一直解析为一个对象Future.这个系统有几种失败的方法,如果在将它们包装成一个之前检查所有这些东西会更方便Future.前往[Book]远为您的银行代码比周围交给其他人更NSArray.Rob*_*Rob 11
基本模式是使用完成处理程序关闭。
例如,我们经常使用Result:
func fetchGenres(completion: @escaping (Result<[Genre], Error>) -> Void) {
...
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
DispatchQueue.main.async {
completion(.failure(error))
}
return
}
// parse response here
let results = ...
DispatchQueue.main.async {
completion(.success(results))
}
}.resume()
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
fetchGenres { results in
switch results {
case .failure(let error):
print(error.localizedDescription)
case .success(let genres):
// use `genres` here, e.g. update model and UI
}
}
// but don’t try to use `genres` here, as the above runs asynchronously
Run Code Online (Sandbox Code Playgroud)
请注意,上面我将完成处理程序分派回主队列以简化模型和 UI 更新。一些开发人员反对这种做法,要么使用所使用的任何队列,要么使用URLSession自己的队列(要求调用者自己手动同步结果)。
但这在这里并不重要。关键问题是使用完成处理程序来指定在异步请求完成时要运行的代码块。
请注意,上面我NSArray不再使用 (我们不再使用那些桥接的 Objective-C 类型)。我假设我们有一个Genre类型,我们大概使用JSONDecoder,而不是JSONSerialization来解码它。但是这个问题没有足够的关于底层 JSON 的信息来深入了解这里的细节,所以我省略了它以避免混淆核心问题,使用闭包作为完成处理程序。
迅捷4.0
对于异步请求-响应,您可以使用完成处理程序。参见下文,我使用完成句柄范例修改了解决方案。
func getGenres(_ completion: @escaping (NSArray) -> ()) {
let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
print(urlPath)
guard let url = URL(string: urlPath) else { return }
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
let results = jsonResult["genres"] as! NSArray
print(results)
completion(results)
}
} catch {
//Catch Error here...
}
}
task.resume()
}
Run Code Online (Sandbox Code Playgroud)
您可以按以下方式调用此函数:
getGenres { (array) in
// Do operation with array
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47406 次 |
| 最近记录: |