Swift 2如何在继续代码之前等待NSURLSessionDataTask完成

时间:2016-07-01 20:44:07

标签: swift2 nsurlsessiondatatask

在此代码中,request.getStatusCode()request.getIsConnected()都在执行task块内的代码之前执行

即。 dataTask.resume()在执行任何后续代码之后才会执行,无论是相同函数,类还是单独类中的代码。

我已经尝试将函数调用放入主队列(串行),全局队列(并发),手动串行队列,手动并发队列和NSOperationQueue,所有后跟aa while循环等待关闭完成。

while isDoingSomething {
    NSThread.sleepForTimeInterval(0.0)
}

环。

我已经从这段代码中删除了任何GCD或操作,以避免我尝试过的每个队列场景的混乱。

ViewController.swift

import Cocoa
class ViewController: NSViewController {
    .
    .
    .
    func login(username username: String, password: String) {
        let url = "https://www.awebsite.com/login"
        let URL = NSURL(string: url)
        let method = "POST"
        let params = "username=\(username)&password=\(password)"
        vis = URLVisitor(URL: URL!, params: params, method: method, jsonParams: [:])
        vis.execute()
        cookies = vis.getCookies()
        let contentsOfURL = vis.getContentsOfURL()
    }
    .
    .
    .
}

URLVisitor.swift

import Cocoa
let queue = NSOperationQueue

class URLVisitor: NSOperation {
    .
    .
    .

    func execute() {
        let request = Request(URL: URL!, params: params, method: method, jsonParams: jsonParams)
        if !self.cookies.isEmpty {
            request._setCookies(self.cookies)
        }

        request._setAuthorizationHeader(self.authorizationHeader)
        request.sendRequest()

        self.statusCode = request.getStatusCode()
        self.isConnected = request.getIsConnected()
    }
    .
    .
    .

}

Request.swift

import Cocoa
class Request: NSOperation {
    .
    .
    .

    func sendRequest() { 
        let session = NSURLSession.sharedSession()
        let request = NSMutableURLRequest(URL: URL)
        request.HTTPMethod = method

        // send jsonParams or params
        if jsonParams.count != 0 {
            do {
                let jsonData = try NSJSONSerialization.dataWithJSONObject(jsonParams, options: .PrettyPrinted)

                request.setValue("aplication/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
                request.HTTPBody = jsonData
            } catch {   
        }
    } else {
        request.HTTPBody = self.params.dataUsingEncoding(NSUTF8StringEncoding)
    }
    let task = session.dataTaskWithRequest(request) {
        (data, response, error) in

    NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies(self.cookies, forURL: self.URL, mainDocumentURL: nil)
        if data != nil {
            self.data = data!
            do {
                let responseHeaders = response as! NSHTTPURLResponse
                self.statusCode = responseHeaders.statusCode

                switch self.statusCode {
                    case 200:
                        print("200: OK. getting contentsOfURL and cookies")
                        self.contentsOfURL = try NSString(contentsOfURL: self.URL, encoding: NSUTF8StringEncoding)
                        self.cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL(self.URL)!

                    case 400:
                        print("400: page not found on web")

                    case 404:
                        print("404: page not found on server")

                    case 407:
                        print("407: failed authenticate proxy credentials")

                    default:
                        print("unable to get statusCode")
                }
            } catch {

            }
        } else {
            print("\(self.statusCode): unable to get response ")
        }   
        NSThread.sleepForTimeInterval(1.0)
    }
    task.resume()
}

1 个答案:

答案 0 :(得分:1)

执行此操作的正确方法是添加完成处理程序

func sendRequest(completion: () -> Void) {
    // ...
    let task = session.dataTaskWithRequest(request) {
        // ...

        completion()
    }
    task.resume()
}

用法:

let r = Request()
r.sendRequest {
    // It's done, do something
}

如果你坚持阻止线程(我希望它不是主线程),请使用信号量。但请记住发信号通知请求是成功还是失败。我看到太多的代码忘记在请求失败时发出信号,因此应用程序只是挂断了。

func sendRequest() {
    let semaphore = dispatch_semaphore_create(0)

    let task = session.dataTaskWithRequest(request) {
        // ...
        dispatch_semaphore_signal(semaphore)
    }
    task.resume()
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
相关问题