在Swift

时间:2016-02-08 19:10:56

标签: ios swift session grand-central-dispatch nsoperation

试图理解我如何安排一个任务落后于另一个,看看GCD和NSOperations,但两者似乎都处于远离核心代码的抽象概念中;其中一部分在其自己的线程上执行!

我尝试了这个代码,这是我能找到的最明显的代码......

    let date = NSDate()
    print("getting Links \(date)")

    let operationQueue: NSOperationQueue = NSOperationQueue.mainQueue()
    let completionBlockOperation: NSBlockOperation = NSBlockOperation.init(
        block: {
            self.reportFini()
        }
    )

    let workerBlockOperation:NSBlockOperation = NSBlockOperation.init(
        block: {
            self.getLinks()
        }
    )
    completionBlockOperation.addDependency(workerBlockOperation)
    operationQueue.addOperation(workerBlockOperation)
    operationQueue.addOperation(completionBlockOperation)

现在,reportFini几乎没有......

func reportFini() {
    let date = NSDate()
    print("got Links \(date)")
}

但getLinks更复杂,使用会话......简而言之,它运行

    let request = NSMutableURLRequest(URL: NSURL(string: "https://blah")!)
    let session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"

    request.addValue("application/json",forHTTPHeaderField: "Content-Type")
    request.addValue("path", forHTTPHeaderField: lePath)
    request.addValue("settings", forHTTPHeaderField: "requested_visibility\": \"public\"}")

    var nodeA:NSMutableDictionary? = ["path":lePath]
    let nodeB:NSMutableDictionary? = ["requested_visibility":"public"]
    nodeA!.setValue(nodeB, forKey: "settings")

    do {
        let jsonData = try NSJSONSerialization.dataWithJSONObject(nodeA!, options: [])
        request.HTTPBody = jsonData
    } catch {
        completion(string: nil, error: error)
    }
    var string2Return = ""
    var stringPath = ""
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if let error = error {
            completion(string: nil, error: error)
            return
        }
        let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
        print("Body: \(strData)\n\n")
        do {
            let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
            self.jsonParser(jsonResult,field2file: "ignore")

            if let stringPath = (self.parsedJson["url"] as? String) {
                string2Return = stringPath
            } else {
                string2Return = (self.parsedJson["error_summary"] as? String)!
            }
            completion(string: string2Return, error: error)
        } catch {
            completion(string: nil, error: error)
        }
    })
    task.resume()

}

现在,getLinks和reportFini都同时执行@;基本上得到链接自己的线程!并立即返回......但是我需要/希望在完成后得到通知,因为我还有别的事要做。

它变得更复杂,因为我需要同时运行10个会话(获取10个链接),所以并行;并希望在他们全部完成后收到通知。

---更新---

尝试将GCD括在

中的会话代码中
    let workerQueue = dispatch_queue_create("getLinks", DISPATCH_QUEUE_CONCURRENT)
    let getLinksGroup = dispatch_group_create()

    dispatch_group_notify(getLinksGroup, dispatch_get_main_queue()) {
        print("All Links Downloaded")
    }

    dispatch_group_enter(getLinksGroup)
    dispatch_group_async(getLinksGroup, workerQueue) {

退出...

    dispatch_group_leave(getLinksGroup)

不幸的是它不起作用;正如我已经看到会话启动他们自己的线程,我几乎立即通知代码已经完成,显然在它实际完成URL数据下载任务之前。

尝试使用KVO ......

1 个答案:

答案 0 :(得分:2)

管理解决这个问题;使用GCD& KVO,但不管理会议;管理计数器,而不是通过更改受监控的KVO值来触发。一个很好的解决方案,你告诉我。

public class SynchronizedInt<T> {
private var blob:Int = 0
private let accessQueue = dispatch_queue_create("SynchronizedIntAccess", DISPATCH_QUEUE_SERIAL)

public func pending(queue2go:T)  {
    dispatch_sync(self.accessQueue) {
        self.blob = queue2go as! Int
    }
}

public func fulfilled() -> Bool {
    dispatch_sync(self.accessQueue) {
        self.blob = self.blob - 1
    }
    if self.blob == 0 {
        return true
    } else {
        return false
    }
}

public func copy() -> Int {
    return self.blob
}

}

我正在使用它来跟踪所启动的会话,因此我可以在完成所有操作时收到通知。我在完成块中跟踪完成,每个完成块检查它是否是最后一个。除此之外,我使用了基于此处提供的第一个Swifty解决方案的各种KVO。

http://blog.scottlogic.com/2015/02/11/swift-kvo-alternatives.html