我有两个关于如何在Objective-C 2.0 +中创建正确的只读属性的问题。
这是我原来的方法,我们称之为解决方案1 :
@interface ClassA{
@private
NSMutableArray *a_;
}
// NOTE: no retain
@property (nonatomic, readonly) NSMutableArray *a;
@end
///////////////////////////////////////
@implementation ClassA
@synthesize a = a_;
- (NSMutableArray *)a{
if(nil == a_){
a_ = [[NSMutableArray alloc] array];
}
// Potential leak warning on the following line.
return a_;
}
- (void)dealloc{
// I released the object here, I think this should be safe.
[a_ release];
[super dealloc];
@end
当我编译和分析它时,系统会发出如下警告:“'返回_'时可能发生泄漏。”
然后我再次阅读Objective-C的文档,并找到另一种方法如下。我们称之为解决方案2 。
@interface ClassB{
@private
NSMutableArray *a_;
}
// NOTE: make it retain+readonly
@property (nonatomic, readonly, retain) NSMutableArray *a;
@end
///////////////////////////////////////
// Add a private category
@interface ClassB ()
// reset the property to readwrite
@property (nonatomic, readwrite, retain) NSMutableArray *a;
@end
//////
@implementation ClassB
@synthesize a = a_;
- (id)init{
if(self = [super init]){
// NOTE: set the value as we use property normally.
self.a = [NSMutableArray array];
}
return self;
}
- (void)dealloc{
self.a = nil;
[super dealloc];
@end
现在,我的问题是:
谢谢你们!
- Tonny
答案 0 :(得分:3)
根据要求,我正在复制我的评论作为答案:
[[NSMutableArray alloc] array]
应该给你一个编译器警告,它肯定会崩溃。你想要[[NSMutableArray alloc] init]
。
答案 1 :(得分:2)
通常,如果您现在只读属性的值将提前,则最好在init方法中进行设置。
我不确定这是否会导致泄漏警告,但我会做类似的事情:
@interface ClassA{
@private
NSMutableArray a_;
}
// NOTE: no retain
@property (nonatomic, readonly) NSMutableArray a;
@end
@implementation ClassB
@synthesize a = a_;
- (id)init{
if(self = [super init]){
// NOTE: set the value as we use property normally.
a_ = [[NSMutableArray alloc] init];
}
return self;
}
- (NSMutableArray *)a
{
return a_;
}
- (void)dealloc{
[a_ release];
[super dealloc];
}
@end
编辑:
修正了a_ assignment。
答案 2 :(得分:2)
老实说,我发现使用“私人”读写属性更容易,而不是对ivars大惊小怪:
MyClass.h
@interface MyClass : NSObject
@property (nonatomic, copy, readonly) NSArray * someArray; // Public
@end
MyClass.m
@interface MyClass () // Class extension
@property (nonatomic, copy, readwrite) NSArray * someArray; // "Private"
@end
@implementation MyClass
@synthesize someArray = someArray_;
- (id)init
{
self = [super init];
if (self != nil)
{
self.someArray = ...; // Array initialization
}
return self;
}
- (void)dealloc
{
[someArray_ release];
[super dealloc];
}
@end
不需要ivars!现代运行时将自动合成它们。您的属性是从外部(即其他类)只读,但在内部,您已将该属性重新声明为读写,因此您可以利用合成属性访问器的便利性。
(当然,我仍然声明明确的ivar合成 - 在此示例中为someArray_
- 用于-dealloc
,因为有充分的理由不使用-dealloc
中的属性并且可能在-init
中。)