I want to create a function which loads data from an url and then returns the responseData as NSData. I want to block the mainThread until the data is finished. Here is what I have so far:
我想创建一个从url加载数据的函数,然后将responseData作为NSData返回。我想阻止mainThread直到数据完成。这是我到目前为止:
Function:
功能:
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()
}
Call:
呼叫:
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
})
I get an error at within the func in line 21:
我在第21行的func中遇到错误:
let task = session.dataTaskWithRequest(request, completionHandler: completion)
Compiler: "Cannot invoke 'dataTaskWithRequest' with an argument list of type '(NSMutableURLRequest, completionHandler: completionBlock)"
编译器:“无法使用类型'(NSMutableURLRequest,completionHandler:completionBlock)的参数列表调用'dataTaskWithRequest'”
3 个解决方案
#1
5
As for question issue: typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
至于问题:typealias CompletionBlock =(NSData!,NSURLResponse!,NSError!) - > NSData
Your completion handler returns NSData
but it shouldn't return anything as in declaration:
您的完成处理程序返回NSData但它不应返回任何声明中的内容:
func dataTaskWithRequest(_ request: NSURLRequest,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)?) -> NSURLSessionDataTask
This caused a type error, because you had provided a wrong closure type
.
这导致了类型错误,因为您提供了错误的闭包类型。
And it is quite reasonable, because dataTaskWithRequest
is designed to be asynchronous. It creates an HTTP request for the specified URL request object, and calls a handler upon completion
. If you really want to make a synchronous request you can use an old NSURLConnection
API with sendSynchronousRequest
, but you shouldn't do it, because synchronous requests are a very bad design choice: they block main UI thread and there is no way to cancel that request except when it errors on its own. That's why Apple created a new NSURLSession
API, based on completion handlers and now deprecated synchronous requests in iOS 9.
这是非常合理的,因为dataTaskWithRequest被设计为异步的。它为指定的URL请求对象创建HTTP请求,并在完成时调用处理程序。如果你真的想要发出同步请求,你可以使用旧的NSURLConnection API和sendSynchronousRequest,但你不应该这样做,因为同步请求是一个非常糟糕的设计选择:它们阻止主UI线程,并且没有办法取消它请求,除非它自己出错。这就是为什么Apple基于完成处理程序创建了一个新的NSURLSession API,现在已经弃用了iOS 9中的同步请求。
#2
1
Doing synchronous request is very bad, but this will do
执行同步请求非常糟糕,但这样做
let request = NSURLRequest() //set all url and method and so
var response: NSURLResponse?
var error: NSError?
NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
important synchronous requests was removed in swift 2.0.
在swift 2.0中删除了重要的同步请求。
#3
0
As Daniel said, this is a bad practice in general. Any time, you have to go out and get data and wait for a response, you should be handling that asynchronously. If not, your UI is going to hang up on the main thread, and the user is likely to think that your app has crashed.
正如丹尼尔所说,这是一种不好的做法。任何时候,你必须出去获取数据并等待响应,你应该异步处理它。如果没有,您的UI将挂在主线程上,用户可能会认为您的应用已崩溃。
Working asynchronously, you will have to keep in mind that your main thread is still working and won't have that data until it receives it in the completion block. If it's imperative, you should throw up a UI element to let the user know you are waiting ie. UIActivityIndicatorView
异步工作时,您必须记住,您的主线程仍在工作,并且在完成块中收到数据之前不会拥有该数据。如果这是必要的,你应该抛出一个UI元素让用户知道你在等待,即。 UIActivityIndicatorView
#1
5
As for question issue: typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
至于问题:typealias CompletionBlock =(NSData!,NSURLResponse!,NSError!) - > NSData
Your completion handler returns NSData
but it shouldn't return anything as in declaration:
您的完成处理程序返回NSData但它不应返回任何声明中的内容:
func dataTaskWithRequest(_ request: NSURLRequest,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)?) -> NSURLSessionDataTask
This caused a type error, because you had provided a wrong closure type
.
这导致了类型错误,因为您提供了错误的闭包类型。
And it is quite reasonable, because dataTaskWithRequest
is designed to be asynchronous. It creates an HTTP request for the specified URL request object, and calls a handler upon completion
. If you really want to make a synchronous request you can use an old NSURLConnection
API with sendSynchronousRequest
, but you shouldn't do it, because synchronous requests are a very bad design choice: they block main UI thread and there is no way to cancel that request except when it errors on its own. That's why Apple created a new NSURLSession
API, based on completion handlers and now deprecated synchronous requests in iOS 9.
这是非常合理的,因为dataTaskWithRequest被设计为异步的。它为指定的URL请求对象创建HTTP请求,并在完成时调用处理程序。如果你真的想要发出同步请求,你可以使用旧的NSURLConnection API和sendSynchronousRequest,但你不应该这样做,因为同步请求是一个非常糟糕的设计选择:它们阻止主UI线程,并且没有办法取消它请求,除非它自己出错。这就是为什么Apple基于完成处理程序创建了一个新的NSURLSession API,现在已经弃用了iOS 9中的同步请求。
#2
1
Doing synchronous request is very bad, but this will do
执行同步请求非常糟糕,但这样做
let request = NSURLRequest() //set all url and method and so
var response: NSURLResponse?
var error: NSError?
NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
important synchronous requests was removed in swift 2.0.
在swift 2.0中删除了重要的同步请求。
#3
0
As Daniel said, this is a bad practice in general. Any time, you have to go out and get data and wait for a response, you should be handling that asynchronously. If not, your UI is going to hang up on the main thread, and the user is likely to think that your app has crashed.
正如丹尼尔所说,这是一种不好的做法。任何时候,你必须出去获取数据并等待响应,你应该异步处理它。如果没有,您的UI将挂在主线程上,用户可能会认为您的应用已崩溃。
Working asynchronously, you will have to keep in mind that your main thread is still working and won't have that data until it receives it in the completion block. If it's imperative, you should throw up a UI element to let the user know you are waiting ie. UIActivityIndicatorView
异步工作时,您必须记住,您的主线程仍在工作,并且在完成块中收到数据之前不会拥有该数据。如果这是必要的,你应该抛出一个UI元素让用户知道你在等待,即。 UIActivityIndicatorView