等待其他进程

Wait for other processes

我必须等待多个后台进程才能执行其他操作,我正在寻找并尝试用它做点什么,但我做不到。这是代码。我评论了部分以解释我想要达到的目标。我可以用完成处理程序来完成,但是这个函数被调用了几次,具体取决于照片的数量。

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])")
        }

    })
}

主队列是一个串行队列,也就是说它以先进先出的顺序一次块执行。枚举中的所有调度都应该在底部的 运行.

之前完成

编辑:刚刚注意到您在完成处理程序中异步。

一件简单的事情就是倒数(因为你知道有多少)。

只需在枚举之前添加 var expectedCompletions = attachement.count,然后在块内将它们倒数 (expectedCompletions--)。到0时,运行最后的代码。

I have to wait for multiple background process before doing other

您真的应该考虑使用 NSOperationQueue 来满足此要求,因为它允许您配置所有已注册操作之间的依赖关系。通过这种方式,您可以配置和添加多个下载,然后配置依赖于所有这些下载的 post 下载操作。操作队列将在所有其他操作完成后处理开始该操作。

这些操作还为您提供了一种很好的方式来取消挂起的上传/下载(如果您不再需要它们)。

您也可以考虑使用 dispatch_groups 来管理它。很难确保您所做的完全正确。

您可以使用 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])")
        }

    })
}