试图理解我如何安排一个任务落后于另一个,看看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 ......
答案 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