title: Thread safe and "Collection was mutated while being enumerated"
body: <p>I have a class "Ad" where I set a static variable inside my Ad.m :</p>
  
  <pre><code>static NSDictionary *citiesDict = nil; // class variable 
  </code></pre>
  
  <p>and in the same file I have implemented a class method that basically load a plist file of the name of cities with their index numbers if it's not already loaded and finally convert the number value passed as paramater to the name of the city : </p>
  
  <pre><code>+(NSString *) cityFromNumberValue:(NSString *)cityNumberValue
  {   
      // load the cities from the plist file named "cities" if it's not already loaded
      if (!citiesDict)
      {  
          NSString *path = [[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"];
  
         citiesDict = [[NSDictionary alloc ]initWithContentsOfFile:path];
         NSLog(@"loading plist");
  
      }
  
  NSLog(@"will return value");
  NSArray *temp = [ citiesDict allKeysForObject:cityNumberValue];  
  NSString *key = [temp lastObject]; 
  return key ;
  }
  </code></pre>
  
  <p>and always in the same file I have implement an init method to convert a Dictionary to an Ad object where It uses the Class method  +cityFromNumberValue:cityNumberValue :</p>
  
  <pre><code>-(id) initWithDictionary: (NSDictionary *) dictionay
  {
      self = [super init];
      if (self)
      {
      // convert the number to name of city
      self.departureCity= [Ad cityFromNumberValue:[dictionay objectForKey:@"ad_villedepart"]]; 
      self.arrivalCity=   [Ad cityFromNumberValue:[dictionay objectForKey:@"ad_villearrivee"]]; 
      }
  return self;
  }
  </code></pre>
  
  <p>And I also have inside the same file a method to fetch Ads from a web service where it calls the method +cityFromNumberValue:cityNumberValue: inside a for loop :</p>
  
  <pre><code>+(NSDictionary *) fetchAdOfPage : (NSInteger) page PerPage : (NSInteger) perPage
  {
      NSMutableArray *  adsArray = [[NSMutableArray alloc] init];
     ...... 
      NSMutableArray *array = [NSArray arrayWithContentsOfURL:url];
  
  // convert the new fetchted dictionnaries of Ads to an Ad objects
  
  for (NSMutableDictionary *dictAd in array) 
  { 
    // convertion using the designated initializer
  
      Ad *ad = [[Ad alloc]initWithDictionary:dictAd]; 
      [adsArray addObject:ad]; 
  
      }
        ....
      return dictFinal ;
  }
  </code></pre>
  
  <p>and somewhere else from mu controller I call this fetch methode like this :</p>
  
  <pre><code> // do request on async thread
          dispatch_queue_t fetchQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
          dispatch_async(fetchQ, ^{
  
              NSDictionary * dict = [Ad fetchAdOfPage:currentPage PerPage:kAdsPerPage];
  
              dispatch_sync(dispatch_get_main_queue(), ^{
                  .....
              });
          });
  
          dispatch_release(fetchQ);
  </code></pre>
  
  <p>now my problem is that last time when I run the app inside the simulator I got an error "Collection was mutated while being enumerated" and it points to the line : </p>
  
  <pre><code> NSArray *temp = [ citiesDict allKeysForObject:cityNumberValue];
  </code></pre>
  
  <p>but I got this error for the first time , I didn't get it before and I use the same code for more than three months and everything is ok , and I can't even reproduce the same error again !  after putting a NSLog to see what is happen I always get : </p>
  
  <pre><code>2013-05-21 19:39:20.141 myApp[744:3b03] loading plist
  2013-05-21 19:39:20.151 myApp[744:6303] will return value
  2013-05-21 19:39:20.151 myApp[744:3b03] will return value
  2013-05-21 19:39:20.152 myApp[744:6303] will return value
  2013-05-21 19:39:20.153 myApp[744:6303] will return value
  2013-05-21 19:39:20.154 myApp[744:6303] will return value
  2013-05-21 19:39:20.153 myApp[744:3b03] will return value
  2013-05-21 19:39:20.155 myApp[744:6303] will return value
  </code></pre>
  
  <p>but one time I got :</p>
  
  <pre><code>2013-05-21 19:39:20.141 myApp[744:3b03] loading plist
  2013-05-21 19:39:20.142 myApp[744:6303] loading plist
  2013-05-21 19:39:20.151 myApp[744:6303] will return value
  2013-05-21 19:39:20.151 myApp[744:3b03] will return value
  2013-05-21 19:39:20.152 myApp[744:6303] will return value
  2013-05-21 19:39:20.153 myApp[744:6303] will return value
  2013-05-21 19:39:20.154 myApp[744:6303] will return value
  2013-05-21 19:39:20.153 myApp[744:3b03] will return value
  2013-05-21 19:39:20.155 myApp[744:6303] will return value
  </code></pre>
  
  <p>the app didn't crash but there is a strange "loading plist" twice since I have checked using the if statement ! so I guess that there is two threads have entered : </p>
  
  <pre><code>if (!citiesDict)
  </code></pre>
  
  <p>at the same time , and then both of them hav set the citiesDict Dictionary and since this dictionary can be used in  </p>
  
  <pre><code> [ citiesDict allKeysForObject:cityNumberValue]; 
  </code></pre>
  
  <p>just after the if statement that can cause the crash "Collection was mutated while being enumerated" , can this be the real senario ? </p>
  
  <p>since I can't reproduce the error again I Wonder if adding : </p>
  
  <pre><code>   @synchronized(citiesDict)
      {
          citiesDict = [[NSDictionary alloc ]initWithContentsOfFile:path];
          NSLog(@"loading plist");
      }
  </code></pre>
  
  <p>can fix that issue ? have you any suggestion to better implement a safer implementation and how we avoid in general the "Collection was mutated while being enumerated" error when we are obliged to work with the same Array from different threads , and can just reading the content of an array from a different threads causes a problem or the problem is just when writing at the same time ? thank you in advance for your help </p>