Lee Armstrong Lee Armstrong - 1 year ago 73
iOS Question

GCD and mutable objects

I have a singleton data manager object that manages the connection to a web service, processes the data and then updates a mutable dictionary with the objects. All requests for this dictionary are via this singleton instance that I have created. Now and again I will get conflicts as I am obviously editing a mutable object from many threads and so get the occasional EXC_BAD_ACCESS.

I could implement @synchronized methods or use NSLock but as I am already making extensive use of Grand Central Dispatch I was wondering if there is anything I can do there by forcing them all down one thread synchronously? I also am not sure if the above methods would work and how they would be implemented.

Example code below. The exception can occur in the getObjectArray method as I could be adding to it/updating sub object/deleting in the translateToObjectFromDict method.

NSMutableDictionary *staticDictionary;

-(NSArray *)getObjectArray{

NSArray *returnArray = [[[NSArray alloc]init]autorelease];
returnArray = [self.staticDictionary allValues];
return returnArray;

-(void)translateToObjectFromDict:(NSDictionary *)sourceDictionary{

dispatch_group_t taskGroup = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0,0);


for (id key in sourceDictionary) {
NSDictionary *subDictionary = [sourceDictionary objectForKey:key];
for (id key in subDictionary) {

NSArray *theObjData = [subDictionary objectForKey:key];
if ([theObjData count] == 12) {

theObj *temptheObj = [[PINKtheObj alloc] initWith......
NSString *unihex = temptheObj.unihex;

if ([self.staticDictionary objectForKey:unihex]){
PINKtheObj *localtheObj = [self.staticDictionary objectForKey:unihex];
if (temptheObj.time > localtheObj.time) {
[localtheObj updatetheObjWith.......
[temptheObj release];
[self.staticDictionary setObject:temptheObj forKey:unihex];


dispatch_group_notify(taskGroup, queue, ^{
NSDictionary *getMainDict = [self.mainDictionary objectForKey:@"theObjs"];

for (id key in self.staticDictionary) {
if (![getMainDict objectForKey:key]){
[self.removeArray addObject:[self.staticDictionary objectForKey:key]];

[[NSNotificationCenter defaultCenter]postNotificationName:@"updated" object:nil];


Answer Source

I think you should supply all your calls (objectForKey:, setObject:ForKey:, etc.) to your staticDictionary in your own serial queue. Create it when singleton initializes and use everywhere.
In your header file create ivar.

dispatch_queue_t queueDict;

In .m file just add to init

queueDict = dispatch_queue_create("com.yourid.yoursingleton.queueDict ", NULL);

When you want to access or put data into dictionary just make

dispatch_async(queueDict, ^(){
[staticDict setObject:obj forKey:key]; //example

You can use dispatch_sync if you want your task to wait for returned value.

__block id returnValue;
dispatch_sync(queueDict, ^(){
returnValue = [statictDict objectForKey:key]; //example
obj = returnValue;