2016-03-14 202 views
1

在做其他事情之前,我必须等待多个后台进程,我正在寻找并试图对此做一些事情,但是我做不到。这是代码。我评论了这些部分以解释我想要达成的目标。我可以用完成处理程序完成,但根据照片数量的不同,此功能会被调用几次。等待其他进程

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

主队列是一个串行队列,这意味着它按照先进先出的顺序一次在块上执行。枚举中的所有调度应该在底部调度运行之前完成。

编辑:只注意到你在完成处理程序异步。

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

只需在枚举前添加var expectedCompletions = attachement.count,然后在块内将其计数(expectedCompletions--)。当它变为0时,最后运行代码。

+1

但他们并不:( – Woodgun11

+0

不好意思,刚才注意到您异步在完成处理程序添加了一个简单的事情,试图 –

+0

这不是安全访问。一个变量来自不同的线程,没有同步 – CouchDeveloper

1

我必须等待多个后台程序做其他

之前,您应该看看在使用NSOperationQueue这一要求,因为它可以让你所有的注册操作之间配置的依存关系。通过这种方式,您可以配置和添加一些下载内容,然后配置依赖于所有这些下载的后下载操作。操作队列将处理在所有其他操作完成时开始该操作。

如果您不再需要这些操作,该操作还会为您提供取消挂起上传/下载的好方法。

你可以选择使用dispatch_group来管理它。很难确保你所做的完全正确。

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

因为这不会阻塞调用线程,所以最好使用'dispatch_group_nofity'来代替'dispatch_group_wait'。 – CouchDeveloper

+0

@CouchDeveloper你是对的,代码相应地改变了。 – mluisbrown