等待其他进程

时间:2016-03-14 13:45:26

标签: ios swift grand-central-dispatch

在做其他事情之前我必须等待多个后台进程,我正在寻找并尝试用此做点什么,但我无法做到。这是代码。我对这些部分进行了评论,以解释我想要达到的目标。我可以使用完成处理程序执行此操作,但根据照片数量调用此函数几次。

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

    })
}

3 个答案:

答案 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时,最后运行代码。