在做其他事情之前我必须等待多个后台进程,我正在寻找并尝试用此做点什么,但我无法做到。这是代码。我对这些部分进行了评论,以解释我想要达到的目标。我可以使用完成处理程序执行此操作,但根据照片数量调用此函数几次。
func prepareArray(stext: NSMutableAttributedString, completionHandler: CompletionHandler) {
self.finalForUpload = [String]()
var attributedArray = [AnyObject]()
var lastRng = 0
let range:NSRange = NSMakeRange(0,stext.length)
stext.enumerateAttributesInRange(range, options: NSAttributedStringEnumerationOptions(rawValue: 0), usingBlock: {(dic: [String:AnyObject]?, range :NSRange!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
let attachement = dic as NSDictionary!
attachement.enumerateKeysAndObjectsUsingBlock({ (key:AnyObject?, obj:AnyObject?, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
let stri = key as! NSString!
if stri == "NSAttachment"{
let att:NSTextAttachment = obj as! NSTextAttachment
if att.image != nil{
print("range location: \(range.location)")
if range.location != lastRng {
attributedArray.append(stext.attributedSubstringFromRange(NSMakeRange(lastRng, range.location-lastRng)))
lastRng = range.length
}
let im:UIImage = att.image!
self.httpManager.uploadPhoto(im, completionHandler: { (imgName) -> Void in
let imName = imgName.characters.dropFirst()
let imageName = String(imName.dropLast())
//WAIT FOR THIS
dispatch_async(dispatch_get_main_queue(), {
print("append")
//stext.attributedSubstringFromRange(range)
attributedArray.append(imageName)
lastRng = range.location
})
})
}
}
})
})
//BEFORE DOING THIS
dispatch_async(dispatch_get_main_queue(), {
if lastRng == 0 && attributedArray.count < 1{
attributedArray.append(stext)
} else {
attributedArray.append(stext.attributedSubstringFromRange(NSMakeRange(lastRng, stext.length-lastRng)))
}
for var i = 0; i<attributedArray.count; i++ {
print("\n \n \(i) : \(attributedArray[i])")
}
})
}
答案 0 :(得分:2)
您可以使用dispatch_group
methods执行此操作。
但是我建议使用像PromiseKit或类似的东西,这样可以更好地控制多个异步块的依赖关系。
以下是使用dispatch_group
方法的代码:
func prepareArray(stext: NSMutableAttributedString, completionHandler: CompletionHandler) {
// create the dispatch group
dispatch_group_t aGroup = dispatch_group_create();
self.finalForUpload = [String]()
var attributedArray = [AnyObject]()
var lastRng = 0
let range:NSRange = NSMakeRange(0,stext.length)
stext.enumerateAttributesInRange(range, options: NSAttributedStringEnumerationOptions(rawValue: 0), usingBlock: {(dic: [String:AnyObject]?, range :NSRange!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
let attachement = dic as NSDictionary!
attachement.enumerateKeysAndObjectsUsingBlock({ (key:AnyObject?, obj:AnyObject?, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
let stri = key as! NSString!
if stri == "NSAttachment"{
let att:NSTextAttachment = obj as! NSTextAttachment
if att.image != nil{
print("range location: \(range.location)")
if range.location != lastRng {
attributedArray.append(stext.attributedSubstringFromRange(NSMakeRange(lastRng, range.location-lastRng)))
lastRng = range.length
}
let im:UIImage = att.image!
// use dispatch_group to coordinate.
// must call before uploadPhoto as we don't know how long it will take
dispatch_group_enter(aGroup);
self.httpManager.uploadPhoto(im, completionHandler: { (imgName) -> Void in
let imName = imgName.characters.dropFirst()
let imageName = String(imName.dropLast())
dispatch_async(aGroup, dispatch_get_main_queue(), {
print("append")
//stext.attributedSubstringFromRange(range)
attributedArray.append(imageName)
lastRng = range.location
// indicate block has completed (reduced group count)
dispatch_group_leave(aGroup);
})
})
}
}
})
})
// wait for all items in group to finish before running this block
dispatch_group_notify(aGroup, dispatch_get_main_queue(), {
if lastRng == 0 && attributedArray.count < 1{
attributedArray.append(stext)
} else {
attributedArray.append(stext.attributedSubstringFromRange(NSMakeRange(lastRng, stext.length-lastRng)))
}
for var i = 0; i<attributedArray.count; i++ {
print("\n \n \(i) : \(attributedArray[i])")
}
})
}
答案 1 :(得分:1)
我必须等待多个后台进程才能执行其他操作
您应该真正考虑使用NSOperationQueue
来满足此要求,因为它允许您配置所有已注册操作之间的依赖关系。通过这种方式,您可以配置和添加大量下载,然后配置依赖于所有这些下载的后期下载操作。当所有其他操作完成时,操作队列将处理启动该操作。
如果您不再需要上传/下载,这些操作也会为您提供一种很好的方法来取消暂停上传/下载。
您也可以考虑使用dispatch_group
来管理它。确保你所做的事情完全正确是比较困难的。
答案 2 :(得分:0)
主队列是一个串行队列,这意味着它以先进先出顺序一次在块上执行。枚举中的所有调度都应该在运行底部的调度之前完成。
编辑:刚刚注意到你在完成处理程序中异步。
一件简单的事情就是倒数(因为你知道有多少)。
只需在枚举之前添加var expectedCompletions = attachement.count
,然后在块内对其进行计数(expectedCompletions--
)。当它变为0时,最后运行代码。