Swift: 阻塞 mainThread 直到函数完成加载数据 / NSURLSession with completionHandler
Swift: Block mainThread until function finished loading data / NSURLSession with completionHandler
我想创建一个函数,它从 url 加载数据,然后 returns 作为 NSData 的 responseData。我想阻塞 mainThread 直到数据完成。这是我目前所拥有的:
函数:
typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
func requestURL(targetUrl: String, httpMethod: String, httpBody: String, completion: CompletionBlock){
// REQUEST
let target = NSURL(string: targetUrl) // URL
let request = NSMutableURLRequest(URL: target!) // REQUEST
// HTTP-METHOD
var method = httpMethod
if method != "POST" { method = "GET" } // STANDARD: GET
request.HTTPMethod = method
// HTTP-BODY
let body = httpBody
if body != "" {
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
}
// NSURLSession
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: completion) // Compiler error!
task.resume()
}
致电:
requestURL(targetURL, "GET", "", { (responseData: NSData!, response: NSURLResponse!, error: NSError!) -> NSData in
if responseData != nil {
let resultString = NSString(data: responseData, encoding: NSUTF8StringEncoding) // NSASCIIStringEncoding
println("DATA:\n\(resultString)")
}
if error != nil {
println("ERROR:\n\(error)")
}
return responseData
})
我在第 21 行的 func 中遇到错误:
let task = session.dataTaskWithRequest(request, completionHandler: completion)
编译器:"Cannot invoke 'dataTaskWithRequest' with an argument list of type '(NSMutableURLRequest, completionHandler: completionBlock)"
至于问题问题:typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
您的完成处理程序 returns NSData
但它不应该 return 声明中的任何内容:
func dataTaskWithRequest(_ request: NSURLRequest,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)?) -> NSURLSessionDataTask
这导致了类型错误,因为您提供了错误的 closure type
。
而且还是比较合理的,因为dataTaskWithRequest
被设计成异步的。它creates an HTTP request for the specified URL request object, and calls a handler upon completion
。
如果你真的想要发出同步请求,你可以使用旧的NSURLConnection
API和sendSynchronousRequest
,但你不应该' t 这样做,因为同步请求是一个 非常糟糕的 设计选择:它们阻塞了主 UI 线程并且没有办法取消该请求,除非它自己的错误。这就是为什么 Apple 基于完成处理程序创建了一个新的 NSURLSession
API,现在 已弃用 同步请求 iOS 9.
做同步请求非常糟糕,但是这样就可以了
let request = NSURLRequest() //set all url and method and so
var response: NSURLResponse?
var error: NSError?
NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
重要 同步请求已在 swift 2.0 中删除。
正如丹尼尔所说,这通常是一种不好的做法。任何时候,你必须出去获取数据并等待响应,你应该异步处理。否则,你的 UI 将在主线程挂起,用户很可能会认为你的应用程序崩溃了。
异步工作时,您必须记住您的主线程仍在工作,并且在完成块中接收到数据之前不会有该数据。如果它是必要的,你应该抛出一个 UI 元素让用户知道你正在等待,即。 UIActivityIndicatorView
我想创建一个函数,它从 url 加载数据,然后 returns 作为 NSData 的 responseData。我想阻塞 mainThread 直到数据完成。这是我目前所拥有的:
函数:
typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
func requestURL(targetUrl: String, httpMethod: String, httpBody: String, completion: CompletionBlock){
// REQUEST
let target = NSURL(string: targetUrl) // URL
let request = NSMutableURLRequest(URL: target!) // REQUEST
// HTTP-METHOD
var method = httpMethod
if method != "POST" { method = "GET" } // STANDARD: GET
request.HTTPMethod = method
// HTTP-BODY
let body = httpBody
if body != "" {
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
}
// NSURLSession
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: completion) // Compiler error!
task.resume()
}
致电:
requestURL(targetURL, "GET", "", { (responseData: NSData!, response: NSURLResponse!, error: NSError!) -> NSData in
if responseData != nil {
let resultString = NSString(data: responseData, encoding: NSUTF8StringEncoding) // NSASCIIStringEncoding
println("DATA:\n\(resultString)")
}
if error != nil {
println("ERROR:\n\(error)")
}
return responseData
})
我在第 21 行的 func 中遇到错误:
let task = session.dataTaskWithRequest(request, completionHandler: completion)
编译器:"Cannot invoke 'dataTaskWithRequest' with an argument list of type '(NSMutableURLRequest, completionHandler: completionBlock)"
至于问题问题:typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
您的完成处理程序 returns NSData
但它不应该 return 声明中的任何内容:
func dataTaskWithRequest(_ request: NSURLRequest,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)?) -> NSURLSessionDataTask
这导致了类型错误,因为您提供了错误的 closure type
。
而且还是比较合理的,因为dataTaskWithRequest
被设计成异步的。它creates an HTTP request for the specified URL request object, and calls a handler upon completion
。
如果你真的想要发出同步请求,你可以使用旧的NSURLConnection
API和sendSynchronousRequest
,但你不应该' t 这样做,因为同步请求是一个 非常糟糕的 设计选择:它们阻塞了主 UI 线程并且没有办法取消该请求,除非它自己的错误。这就是为什么 Apple 基于完成处理程序创建了一个新的 NSURLSession
API,现在 已弃用 同步请求 iOS 9.
做同步请求非常糟糕,但是这样就可以了
let request = NSURLRequest() //set all url and method and so
var response: NSURLResponse?
var error: NSError?
NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
重要 同步请求已在 swift 2.0 中删除。
正如丹尼尔所说,这通常是一种不好的做法。任何时候,你必须出去获取数据并等待响应,你应该异步处理。否则,你的 UI 将在主线程挂起,用户很可能会认为你的应用程序崩溃了。
异步工作时,您必须记住您的主线程仍在工作,并且在完成块中接收到数据之前不会有该数据。如果它是必要的,你应该抛出一个 UI 元素让用户知道你正在等待,即。 UIActivityIndicatorView