Coocoo4Cocoa Coocoo4Cocoa - 1 year ago 68
Objective-C Question

iPhone use of mutexes with asynchronous URL requests

My iPhone client has a lot of involvement with asynchronous requests, a lot of the time consistently modifying static collections of dictionaries or arrays. As a result, it's common for me to see larger data structures which take longer to retrieve from a server with the following errors:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSCFArray: 0x3777c0> was mutated while being enumerated.'

This typically means that two requests to the server come back with data which are trying to modify the same collection. What I'm looking for is a tutorial/example/understanding of how to properly structure my code to avoid this detrimental error. I do believe the correct answer is mutexes, but I've never personally used them yet.

This is the result of making asynchronous HTTP requests with NSURLConnection and then using NSNotification Center as a means of delegation once requests are complete. When firing off requests that mutate the same collection sets, we get these collisions.

Answer Source

If it's possible that any data (including classes) will be accessed from two threads simultaneously you must take steps to keep these synchronized.

Fortunately Objective-C makes it ridiculously easy to do this using the synchronized keyword. This keywords takes as an argument any Objective-C object. Any other threads that specify the same object in a synchronized section will halt until the first finishes.

-(void) doSomethingWith:(NSArray*)someArray
    // the synchronized keyword prevents two threads ever using the same variable
       // modify array

If you need to protect more than just one variable you should consider using a semaphore that represents access to that set of data.

// Get the semaphore.
id groupSemaphore = [Group semaphore];

    // Critical group code.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download