我尝试在objective-c中尝试声明为copy和readonly的属性,具体来说,我是否必须自己复制。在我的init方法中。证据表明我做了:
@interface A : NSObject
@property(nonatomic, copy, readonly) NSData *test;
- (instancetype)initWithData:(NSData *)data;
@end
@implementation A
- (instancetype)initWithData:(NSData *)data {
if ((self = [super init]) != nil) {
_test = data;
}
return self;
}
@end
int main (void) {
NSData *d1 = [NSMutableData dataWithBytes:"1234" length:5];
A *a = [[A alloc] initWithData:d1];
NSLog(@"%lx", (unsigned long)d1);
NSLog(@"%lx", (unsigned long)a.test);
return 0;
}
我以为我可以在我的init方法中执行self.test = data
,但这是不允许的,因为它只读(非意外)。当然,self.test = [data copy]
可以确保两个不同的对象。
所以:有没有办法在objective-c中创建一个复制传入值的readonly属性,或者它是否足以构成组合毫无意义的边缘情况,我必须手动复制自己?
答案 0 :(得分:1)
@property
声明只是一些accessor / mutator方法声明的简写,并且(在某些情况下)是所述accessor / mutator方法的合成实现。
在您的情况下,@property(nonatomic, copy, readonly) NSData *test
声明扩展为此等效代码:
@interface A : NSObject
{
NSData* _test;
}
- (NSData*)test;
@end
@implementation A
- (NSData*)test
{
return _test;
}
@end
没有setTest:
mutator方法,因为该属性声明为readonly
,因此copy
属性无效。
您可以实现自己的mutator方法:
- (void)setTest:(NSData*)newValue
{
_test = [newValue copy];
}
或者,您可以让编译器通过在实现文件中声明私有类扩展中的读/写属性来为您合成mutator方法:
// A.m:
@interface A()
@property (nonatomic, copy) NSData* test;
@end
这两种情况都允许您使用test
mutator方法将值复制到_test
实例变量:
- (instancetype)initWithData:(NSData *)data {
if ((self = [super init]) != nil) {
self.test = data;
}
return self;
}
最终结果是:
@interface A : NSObject
@property(nonatomic, copy, readonly) NSData* test;
- (instancetype)initWithData:(NSData*)data;
@end
@interface A()
@property (nonatomic, copy) NSData* test;
@end
@implementation A
- (instancetype)initWithData:(NSData*)data {
if ((self = [super init]) != nil) {
self.test = data;
}
return self;
}
@end
答案 1 :(得分:0)
除了Darren所说的,copy
属性描述了属性设置器具有的语义。在初始值设定项中,您没有使用setter,而是直接分配给实例变量。
可能有点难以理解,但实例变量与属性不同。在这种情况下,使用来实现属性。但是,分配实例变量与设置属性不同。
如果您希望初始化程序也具有复制传入数据的语义,那么这是一个单独的设计决策(尽管最好使用属性的语义)。您可以通过使用Darren建议的私有设置器来实现它,但您也可以这样做:
_test = [data copy];
初始化程序中的。