2

I want to run a for loop with background code, that has something happen once it's finished iterating through every item. To do this without background code would be simple, like this:

for aString: String in strings {
    if string.utf8Length < 4 {
        continue
    }

    //Some background stuff
}

//Something to do upon completion

But to include background code in there means that the code to perform upon completion gets performed before all items are dealt with.

for aString: String in strings {
    if string.utf8Length < 4 {
        continue
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
        //Some background stuff
    }
}

//Something to do upon completion

I'm wondering if it's possible to do that.

Andrew
  • 7,693
  • 11
  • 43
  • 81

1 Answers1

4

Consider using a dispatch group. This provides a mechanism that notifies you when the dispatched tasks finish. So rather than dispatch_async, use dispatch_group_async:

let group = dispatch_group_create();

for aString: String in strings {
    if aString.utf8Length >= 4 {
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
            //Some background stuff
        }
    }
}

dispatch_group_notify(group, dispatch_get_main_queue()) {
    // whatever you want when everything is done
}

FYI, here is an operation queue rendition of the same idea (though something that constrains the number of concurrent operations).

let queue = NSOperationQueue()
queue.name = "String processing queue"
queue.maxConcurrentOperationCount = 12

let completionOperation = NSBlockOperation() {
    // what I'll do when everything is done
}

for aString: String in strings {
    if aString.utf8Length >= 4 {
        let operation = NSBlockOperation() {
            // some background stuff
        }
        completionOperation.addDependency(operation)
        queue.addOperation(operation)
    }
}

queue.addOperation(completionOperation)
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • If you want to block until the background tasks finish, using `dispatch_group_wait` instead of `dispatch_group_notify`. – rob mayoff Feb 21 '15 at 19:02
  • @robmayoff Agreed. But of course, you'd generally avoid doing `dispatch_group_wait` from the main thread. – Rob Feb 21 '15 at 19:07