在Objective-C中,将NSString / NSArray / NSDictionary声明为副本是常见的,是否有必要为readonly属性执行此操作,或者没有区别?如果NSString是只读的,它永远不会被设置,所以声明它强或复制会产生相同的效果吗?
//在这里使用强而非复制,因为它会起作用 永远不会被复制?
@property(nonatomic,readonly)NSString * string;
答案 0 :(得分:5)
如果它确实是只读的,那么您不需要指定它。如果您要私下将其重新声明为readwrite
,那么您确实要指定它。对于readonly
属性,它不起作用,因为不会创建任何setter。
答案 1 :(得分:0)
你是对的,但还有一些事情需要考虑。这很好,因为你的属性是不可变对象。然而,并非总是如此。
我经常遇到的第一个例子是你的实现中有实际可变对象的时候。就像在实现中声明NSArray的属性一样,实际上可以是NSMutableArray。它的强引用属性getter将返回指向NSMutableArray的指针。并且,在某些时候,当你从对象请求NSArray时,你会遇到这种情况,并且需要花费一些时间而不是 - 繁荣! - 你的NSArray有多少不同的元素?我勒个去?在这种情况下,最好在getter中复制使用NSMutableArray的内部实现。
另一个例子是一些模型对象
@interface Person : NSObject <NSCopying>
@property NSString *name;
@property NSDate *birthdate;
@end
你还有一些其他的属性接口
@property (strong, readonly) Person *person;
是的,您不会将不同的对象分配给此属性。但是,您可以修改其字段,因此它将代表一些完全不同的Person。如果您不想要这样的行为 - 请将其设为copy
财产。或者使用访问方法将其设为私有以获取其字段
- (id) getHiddenPersonPropertyValueForKey:(NSString *)personPropertyKey;
或任何其他方式
答案 2 :(得分:0)
如果property表示真正不可变的值(NSArray
,NSIndexSet
等),那么只需readonly
即可,因为它将按原样返回为不可变。
但是如果您的私人ivar是可变的(NSMutableArray
ivar vs property&#39; s NSArray
类型),您应该返回一份副本以防止未来内部更改泄漏到呼叫者&#39;国家。
@interface MyObject : NSObject {
NSMutableArray *_array;
}
@property(nonatomic, readonly) NSArray *array;
// -or-
- (NSArray *)array;
@end
和
@implementation
@dynamic array; // only if @property was declared in interface
- (NSArray *)array
{
return [_array copy];
}
@end
然后,来电者可以安全地保存物业的价值,并且即使不自行制作明确的副本,也希望不更改:
self.array = [myObject array]; // e.g. 1 element
[myObject addElementToArray:@(42)];
NSLog(@"%@", self.array); // still 1 element