我不确定我是否理解如何分配和保留工作。
最近我发现NSString属性没有保留,我设置它时必须添加[myString copy]。这让我想知道我是否误解了使用retain / alloc
的整个方式请有人告诉我,如果我做得对吗?我看了很多并看了一下开源项目,这让我觉得从一开始我就错了。
这是我的方式:
/**** VIEW.h *****/
#import "MyClass.h"
@interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
@property (nonatomic, retain) MyClass *myObject;
- (void)defineObject;
@end
/**** VIEW.m *****/
#import "VIEW.h"
@implementation MyViewController
@dynamic myObject;
- (void)viewDidLoad
{
[super viewDidLoad];
[self defineObject];
NSLog(@"My object's name is: %@", myObject.name);
}
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "@property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:@"my name"];
}
/**** MyClass.h *****/
@interface MyClass : NSObject {
//not sure if this line is still necessary
NSString *name;
}
@property (nonatomic, retain) NSString *name;
- (id)initPersonalised;
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
/**** MyClass.m *****/
#import "MyClass.h"
@implementation MyClass
@dynamic name;
(id)initPersonalised{
self = [super init];
name = @"Undefined";
}
- (void)setName:(NSString *)name{
self.name = [name copy];
}
- (NSString *)name{
return [self.name copy];
}
@end
我希望你能带来一些亮点,经过几个月的编程后,我越来越不确定做得好。
答案 0 :(得分:1)
您可以查看Memory Management Guide。它将帮助您更好地理解alloc&保留概念;希望这可以帮助你。
答案 1 :(得分:1)
Alloc和init是总是齐头并进的方法。 alloc
为您的对象分配空间,init将您的对象初始化为某个值。当您调用alloc时,您有责任以后释放该对象。如果您调用copy,则还要负责稍后释放该对象。在分配对象后立即初始化对象被认为是一种好习惯。
现在,回答我在您的代码中发现的问题。
@interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
这条线是否必要?那要看。您的对象是否具有MyClass作为属性是否有意义?这是一个只有您可以根据您的设计回答的问题。我建议你更深入地研究面向对象的编程。
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "@property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:@"my name"];
}
不一定。您只是提供指向指定类型的对象的指针。设置属性的那一刻,根据属性修饰符,您的类将知道如何处理MyObject。
通过这种方式,无需拨打[yourObject copy]
。这样,您的属性将被复制而不是被保留。只是不要忘记稍后在-dealloc方法中释放它,就像保留属性一样。
总而言之,我建议你多学习一下这个:
答案 2 :(得分:1)
这确实是每个Objective C程序员偶然发现的主题。有一些事情需要知道:
实例变量与媒体资源访问权限
在 MyViewController 中,
myObject = xxx;
和
self.myObject = xxx;
是两件不同的事情。第一个直接分配给实例变量,既不释放旧引用的insance也不保留新分配的实例。后者使用属性setter,因此释放旧值并保留新值。
<强>取消分配强>
即使您声明了已实现的属性,该属性负责保留和释放值,但当您的对象(在您的情况下为 MyViewController )被释放时,它也不会处理释放。因此,您必须在 dealloc :
中明确发布它-(void) dealloc {
[myObject release];
[super dealloc];
}
现在代码:
摘录:
myObject = [[MyClass alloc] initPersonalised];
完全没问题。创建对象时,使用 alloc 和 initXXX 对。始终创建一个实例,引用计数设置为1.因此,通过直接将其分配给实例变量,可以创建一个干净的星座。我没有看到创建实例的其他方法。
在 MyClass 中,您可以使用@synthesize name
代替@dynamic
。然后编译器会自动实现name
和setName:
,你不需要自己动手。
最后,您遗失了dealloc
。
<强>更新强>
如果您使用:
self.myObject = [[MyClass alloc] initPersonalised];
然后你有内存泄漏,因为 initPesonalised 将引用计数设置为1,myObject的setter将它增加到2。如果你想使用setter,那么我必须是:
MyClass* mo = [[MyClass alloc] initPersonalised];
self.myObject = [[MyClass alloc] initPersonalised];
[mo release];
如果您没有使用initXXX
来创建新实例,那将会有所不同。例如,类NSString有许多名为stringXXX
的方法,它们创建一个新的实例(或返回一个共享的实例),它具有(概念上)引用计数为1,稍后会自动减1。然后你最好使用setter:
self.name = [NSString stringWithFormat: @"instance %d", cnt];
如果你想使用 copy 而不是 retain 作为你的字符串属性(这是一个好习惯),那么你可以简单地声明你的属性:
@property (nonatomic, copy) NSString *name;
当您使用@synthesize
实现getter和setter时,编译器将使用 copy 而不是 retain 生成它们。
即使您使用NSString *name;
和/或@property
来实现该属性,也必须@synthesize
。