I would like to use dynamic properties with generic getter/setter, but it seems that in some cases ARC releases an object when it should not. I give here the simplest code to show the problem.
Code that works:
I have the class Person with one dynamic property 'name'
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@end
In the implementation, the 2 methods have the minimal code to be able to set the person's name. I removed the getter part of the code.
@implementation Person
@dynamic name;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
// Setter signature for a NSString
return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
// Get the NSString to set
NSString *s;
[invocation getArgument:&s atIndex:2];
NSLog(@"The string is: %@",s);
}
@end
In my UIViewController, I have one button:
- (IBAction)OnTestClicked:(id)sender
{
Person *p = [[Person alloc] init];
p.name = @"John Doe";
}
and the test works just fine. I got the Log
The string is: John Doe
If I click the button 10 times, I have 10 times the correct Log
The Problem
If the value @"John Doe" is not a string literal, the app will crash when I click the test button a second time.
Here is an example using a private property 'defaultName' that does not use a string literal.
@interface MyViewController ()
@property (strong, nonatomic) NSString *defaultName;
@end
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.defaultName = [[NSString alloc] initWithFormat:@"John Doe"];
}
- (IBAction)OnTestClicked:(id)sender
{
Person *p = [[Person alloc] init];
p.name = self.defaultName;
}
If a click the test button more than once, I got the messages
malloc: *** error for object 0xa8257b0: pointer being freed was not allocated
or
malloc: *** error for object 0x8f68430: double free
It seems that ARC is releasing the strong property 'DefaultName'. But because I am using ARC, I cannot add a retain in the setter....
How do I solve this problem?
Thank you