Objective-c 只读复制属性和 ivars
Objective-c readonly copy properties and ivars
我试图理解在 objective-c 中声明为复制和只读的属性,具体来说,我是否必须自己进行复制。在我的初始化方法中。证据表明我这样做:
@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 中创建一个只读的 属性 来复制传入的值,或者它是否足以使组合毫无意义的边缘情况,我必须做任何还是手动复制我自己?
@property
声明只是 shorthand 一些 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:
修改器方法,因为属性被声明为readonly
,所以copy
属性没有效果。
您可以实现自己的修改器方法:
- (void)setTest:(NSData*)newValue
{
_test = [newValue copy];
}
或者,您可以通过在实现文件的私有 class 扩展中声明 read/write 属性 让编译器为您合成一个修改器方法:
// A.m:
@interface A()
@property (nonatomic, copy) NSData* test;
@end
这两种情况都允许您使用 test
增变器方法将值复制到 _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
除了 Darren 所说的之外,copy
属性还描述了属性 setter 具有的语义。在您的初始化程序中,您没有使用 setter,而是直接分配给实例变量。
可能有点难理解,但是实例变量和属性不是一回事。在这种情况下,它被用来 来实现 和 属性。但是,分配给实例变量与设置 属性.
不同
如果您希望您的初始化器也具有复制传入数据的语义,那是一个单独的设计决策(尽管使用 属性 的语义是个好主意)。您可以按照 Darren 的建议使用私有 setter 来实现它,但您也可以这样做:
_test = [data copy];
在初始化程序中。
我试图理解在 objective-c 中声明为复制和只读的属性,具体来说,我是否必须自己进行复制。在我的初始化方法中。证据表明我这样做:
@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 中创建一个只读的 属性 来复制传入的值,或者它是否足以使组合毫无意义的边缘情况,我必须做任何还是手动复制我自己?
@property
声明只是 shorthand 一些 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:
修改器方法,因为属性被声明为readonly
,所以copy
属性没有效果。
您可以实现自己的修改器方法:
- (void)setTest:(NSData*)newValue
{
_test = [newValue copy];
}
或者,您可以通过在实现文件的私有 class 扩展中声明 read/write 属性 让编译器为您合成一个修改器方法:
// A.m:
@interface A()
@property (nonatomic, copy) NSData* test;
@end
这两种情况都允许您使用 test
增变器方法将值复制到 _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
除了 Darren 所说的之外,copy
属性还描述了属性 setter 具有的语义。在您的初始化程序中,您没有使用 setter,而是直接分配给实例变量。
可能有点难理解,但是实例变量和属性不是一回事。在这种情况下,它被用来 来实现 和 属性。但是,分配给实例变量与设置 属性.
不同如果您希望您的初始化器也具有复制传入数据的语义,那是一个单独的设计决策(尽管使用 属性 的语义是个好主意)。您可以按照 Darren 的建议使用私有 setter 来实现它,但您也可以这样做:
_test = [data copy];
在初始化程序中。