我不确定我是否理解了alloc和retain的工作原理。
最近,我发现NSString属性没有保留,在设置它们时,我必须添加myString副本。这让我想知道我是否误解了保留/分配的整个使用方式
有没有人能告诉我我做得是否正确?我读了很多关于开源项目的书,这让我意识到我可能从一开始就错了。
下面是我的方法:
/**** 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我希望你能带来一点启发,经过几个月的这种编程,我越来越不确定能把它做好。
发布于 2011-05-15 16:36:19
这确实是每个Objective C程序员都会遇到的话题。有几件事需要知道:
实例变量与属性访问
在MyViewController中,
myObject = xxx;和
self.myObject = xxx;是两件不同的事情。第一个直接赋值给实例变量,既不释放到旧的引用实例,也不保留新赋值的实例。后者使用属性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的设置器将其增加到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生成它们。
即使您使用@property和/或@synthesize来实现属性,NSString *name;也是必需的。
发布于 2011-05-15 16:28:57
你可以看看Memory Management Guide。它将帮助您更好地理解分配和保留概念;希望这对您有所帮助。
发布于 2011-05-15 16:35:00
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方法中释放它,就像保留属性一样。
总而言之,这是我建议你多学习的内容:
https://stackoverflow.com/questions/6007230
复制相似问题