title: Message sent to deallocated instance with ARC using custom getter and setter
body: <p>I'm trying to implement a custom getter and setter for my custom object <code>HFObject</code> and my app crashed with a <code>Message sent to deallocated instance</code> error despite using ARC.</p>
  
  <p>I've read every single related post, the ones that were written pre-ARC don't apply, and everything else didn't help. I have the zombie object debugger option turned on.</p>
  
  <hr>
  
  <h2>Setting up the custom HObject</h2>
  
  <p>Within HObject.h I have declared these four properties:</p>
  
  <pre><code>@property (retain) NSString *email;        //Will use custom getter/setter
  @property (retain) NSString *firstName;    //Will use custom getter/setter
  @property (retain) NSDate *date;           //Will use custom getter/setter
  @property (nonatomic, retain) NSMutableDictionary *values;
  </code></pre>
  
  <p>In the implementation of HObject, I have removed the automatic getting and setting of <code>email</code>. <code>firstName</code>, and <code>date</code> by utilizing <code>@dynamic</code> like so</p>
  
  <pre><code>@dynamic email;
  @dynamic firstName;
  @dynamic date;
  </code></pre>
  
  <p>I also allocate the <code>values</code>  dictionary in my HObject init</p>
  
  <pre><code>- (id)init {
      self = [super init];
  
      if (self) {
          self.values = [NSMutableDictionary dictionary];
      }
  
      return self;
  }
  </code></pre>
  
  <hr>
  
  <h2>Implementing Custom Getter &amp; Sender</h2>
  
  <p>For my custom getter/setter. I have overridden </p>
  
  <p><code>- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector</code> </p>
  
  <p>and</p>
  
  <pre><code>- (void)forwardInvocation:(NSInvocation *)invocation
  </code></pre>
  
  <p>As shown below:</p>
  
  <pre><code>- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
  {
      NSString *sel = NSStringFromSelector(selector);
      if ([sel rangeOfString:@"set"].location == 0) {
          return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
      } else {
          return [NSMethodSignature signatureWithObjCTypes:"@@:"];
      }
  }
  
  - (void)forwardInvocation:(NSInvocation *)invocation
  {
      NSString *key = NSStringFromSelector([invocation selector]);
      if ([key rangeOfString:@"set"].location == 0) { 
          key = [key substringWithRange:NSMakeRange(3, [key length]-4)]; 
  
          id obj;   
          [invocation getArgument:&amp;obj atIndex:2];   
  
          [self.values setObject:obj forKey:key];
      } else {
          id obj = [self.values objectForKey:key];
  
          [invocation setReturnValue:&amp;obj];
      }
  }
  </code></pre>
  
  <p>What I'm trying to do here is store all of the values of the property into my <code>values</code> dictionary and retrieve them from there as well.</p>
  
  <hr>
  
  <h2>App Crashing</h2>
  
  <p>In the implementation of my view controller, I try to create a HObject and set values for my properties, and then I log the values dictionary to see all of my values.</p>
  
  <pre><code>- (void)buttonPressed:(id)sender {
      HObject *obj = [[HObject alloc] init];
  
      NSString *name = @"this is a string object";
      obj.date = [NSDate date];
      obj.email = @"email@website.com";
      obj.firstName = [NSString stringWithFormat:@"%@", name];
  
  
      NSLog(@"Values %@", [obj values]);
  }
  </code></pre>
  
  <p>At that point the app crashes and this is my console log</p>
  
  <pre><code>2014-07-27 04:12:37.899 App[61501:60b] Values {
      Date = "2014-07-27 08:12:37 +0000";
      Email = "email@website.com";
      FirstName = "this is a string object";
  }
  2014-07-27 04:12:37.901 HeadsUp[61501:60b] *** -[CFString release]: message sent to deallocated instance 0x109473fe0
  </code></pre>
  
  <p>If you can help me from here, I would greatly appreciate it. I am also including my debugging process in case that will help you</p>
  
  <hr>
  
  <h2>My debugging Process (Long, skip if you can already help me)</h2>
  
  <p>I originally created many of these objects and stored them in an array, and when I do that, as opposed to creating a single object. my app crashed a bit different.</p>
  
  <p>My array:</p>
  
  <pre><code>@property (nonatomic, strong) NSArray *array;
  </code></pre>
  
  <p>Methods:</p>
  
  <pre><code>- (void)createArray
  {
      int i = 1; //number of testobjs
  
      NSMutableArray *objects = [NSMutableArray arrayWithCapacity:i];
  
      for (int j = 0; j&lt;i; j++) {
          HFObject *obj = [[User alloc] init];
  
          NSString *name = @"this is a string object";
          [obj setObject:[NSDate date] forKey:@"Date"];
          obj.email = @"email@website.com";
          obj.firstName = [NSString stringWithFormat:@"%@", name];
  
          [objects addObject:obj];
      }
  
  
      self.array = [NSArray arrayWithArray:objects];
  
  }
  
  - (void)buttonPressed:(id)sender {
      HObject *object = [self.array objectAtIndex:0];
  
      NSLog(@"Values %@", [object values]);
  }
  </code></pre>
  
  <p>Crash log:</p>
  
  <pre><code>2014-07-27 04:34:02.893 App[61623:60b] *** -[CFString isNSString__]: message sent to deallocated instance 0x1094988f0
  (lldb) 
  </code></pre>
  
  <p>Now this crash log is almost the same as the one before, except this didn't log the values inside of <code>[object values]</code></p>
  
  <p>Investigating the issue a bit, I looked at the left window (not sure what it is actually called) of the debugger and I saw this:</p>
  
  <p><img src="https://i.stack.imgur.com/vjRpb.png" alt="()"></p>
  
  <p>(Treat <code>HFObject</code> as <code>HObject</code> and <code>dirtyValues</code> as <code>values</code>; I renamed them for presentational purposes)</p>
  
  <p>You can see that under the key <code>@"FirstName"</code> there is no value.</p>
  
  <p>I did several similar tests where I changed the values of the properties I was setting and changed the data types. More often than not, not only did <code>FirstName</code> not have a value, neither did <code>Date</code>. However, the value of email was always present.</p>
  
  <p>After researching about dataTypes, I realized it was because <code>email</code> was a <code>string literal</code> which can't deallocated. On the other hand <code>firstName</code> and <code>date</code> were objects, which can be deallocated.</p>
  
  <p>The crash log refers to a <code>CFString</code> property, which I learned doesn't use ARC. I never created a Core Foundation object, so I set out to found out it was being created in setter by logging the <code>[obj class]</code>:</p>
  
  <pre><code>- (void)forwardInvocation:(NSInvocation *)invocation
  {
      NSString *key = NSStringFromSelector([invocation selector]);
      if ([key rangeOfString:@"set"].location == 0) { 
          key = [key substringWithRange:NSMakeRange(3, [key length]-4)]; 
  
          id obj;   
          [invocation getArgument:&amp;obj atIndex:2];   
  
          NSLog(@"%@", [obj class]);  //I ADDED THIS LOG
  
          [self.values setObject:obj forKey:key];
      } else {
          id obj = [self.values objectForKey:key];
  
          [invocation setReturnValue:&amp;obj];
      }
  }
  </code></pre>
  
  <p>After crashing one more time, I got the <code>obj</code> classes</p>
  
  <pre><code>2014-07-27 04:58:03.893 HeadsUp[61765:60b] __NSDate
  2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFConstantString
  2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFString
  2014-07-27 04:58:03.904 HeadsUp[61765:60b] *** -[__NSDate release]: message sent to deallocated instance 0x109554370
  (lldb) 
  </code></pre>
  
  <p>Here you can see <code>Date</code> is being deallocated for some reason, and my string are now <code>__NSCF</code> strings.</p>
  
  <p>I tried resetting the strings to <code>NSStrings</code> using <code>(__brigde NSString *)obj</code> and every other possible way you can bridge a CF object to ARC, however that didn't work either.</p>
  
  <p>Here is everything I've done. I appreciate any and all help.</p>