0

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

即 dataTask.resume() 直到任何后续代码执行后才会执行,无论是同一函数、类或单独类中的代码。

我尝试将函数调用放在主队列(串行)、全局队列(并发)、手动串行队列、手动并发队列和 NSOperationQueue 中,然后都是一个 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()
    }
    .
    .
    .

}

请求.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()
}
4

1 回答 1

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)
}
于 2016-07-01T22:44:58.323 回答