0

我想创建一个从 url 加载数据然后将 responseData 作为 NSData 返回的函数。我想阻塞 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)

编译器:“无法使用类型为“(NSMutableURLRequest,completionHandler:completionBlock)的参数列表调用'dataTaskWithRequest'”

4

3 回答 3

5

至于问题:typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData

您的完成处理程序返回NSData,但它不应该像声明中那样返回任何内容:

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。如果你真的想发出一个同步请求,你可以使用一个旧的NSURLConnectionAPI sendSynchronousRequest,但你不应该这样做,因为同步请求是一个非常糟糕的设计选择:它们阻塞主 UI 线程并且没有办法取消该请求,除非当它自己出错时。这就是为什么 AppleNSURLSession基于完成处理程序创建了一个新的 API,并且现在在 iOS 9 中不推荐使用同步请求。

于 2015-08-25T09:40:24.393 回答
1

做同步请求是非常糟糕的,但这会做

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 中删除了重要的同步请求。

于 2015-08-25T09:44:45.353 回答
0

正如丹尼尔所说,这通常是一种不好的做法。任何时候,您都必须出去获取数据并等待响应,您应该异步处理。否则,您的 UI 将挂在主线程上,用户可能会认为您的应用程序已崩溃。

异步工作时,您必须记住,您的主线程仍在工作,并且在完成块中接收到数据之前不会拥有该数据。如果它是必要的,你应该抛出一个 UI 元素让用户知道你在等待,即。UIActivityIndi​​catorView

于 2016-02-17T16:58:52.200 回答