Swift:阻塞mainThread,直到函数用completionHandler加载数据/ NSURLSession

ixa*_*any 0 completionhandler nsurlsession swift

我想创建一个从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()

}
Run Code Online (Sandbox Code Playgroud)

呼叫:

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
    })
Run Code Online (Sandbox Code Playgroud)

我在第21行的func中遇到错误:

let task = session.dataTaskWithRequest(request, completionHandler: completion)
Run Code Online (Sandbox Code Playgroud)

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

Ole*_*rov 5

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

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

func dataTaskWithRequest(_ request: NSURLRequest,
   completionHandler completionHandler: ((NSData!,
                              NSURLResponse!,
                              NSError!) -> Void)?) -> NSURLSessionDataTask
Run Code Online (Sandbox Code Playgroud)

这导致了类型错误,因为您提供了错误closure type.

而这是相当合理的,因为dataTaskWithRequest被设计成异步的.它creates an HTTP request for the specified URL request object, and calls a handler upon completion.如果你真的想要发一个同步请求你可以使用旧的NSURLConnectionAPI sendSynchronousRequest,但你不应该这样做,因为同步请求是一个非常糟糕的设计选择:它们阻止主UI线程,除了取消该请求之外没有办法除外当它自己出错时.这就是为什么Apple NSURLSession基于完成处理程序创建了一个新的API,现在已经弃用了iOS 9中的同步请求.