我想使用带有通用getter / setter的动态属性,但似乎在某些情况下ARC会在不应该的情况下释放一个对象。我在这里给出了最简单的代码来说明问题。
我的Person类有一个动态属性'name'
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@end
在实现中,2种方法具有最小的代码,可以设置人名。我删除了代码的getter部分。
@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
在我的UIViewController中,我有一个按钮:
- (IBAction)OnTestClicked:(id)sender
{
Person *p = [[Person alloc] init];
p.name = @"John Doe";
}
并且测试工作正常。我得到了日志
字符串是:John Doe
如果我单击按钮10次,我有10次正确的日志
如果值 @“John Doe”不是字符串文字,那么当我再次点击测试按钮时应用程序将崩溃。
以下是使用不使用字符串文字的私有属性“defaultName”的示例。
@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;
}
如果多次单击测试按钮,我收到了消息
malloc:***对象0xa8257b0的错误:释放的指针未分配
或
malloc:***对象0x8f68430的错误:双重免费
似乎ARC正在发布强大的属性'DefaultName'。但是因为我使用的是ARC,所以我无法在setter中添加一个保留....
如何解决这个问题?
谢谢
答案 0 :(得分:3)
使用__unsafe_unretained
可以解决问题:
- (void)forwardInvocation:(NSInvocation *)invocation
{
// Get the NSString to set
__unsafe_unretained NSString *s;
[invocation getArgument:&s atIndex:2];
NSLog(@"The string is: %@",s);
}
因为getArgument:
只是将参数复制到给定的缓冲区中,而不是
保留它。