如何保留我自己的对象和属性

时间:2011-05-15 08:02:24

标签: objective-c ios

我不确定我是否理解如何分配和保留工作。

最近我发现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

我希望你能带来一些亮点,经过几个月的编程后,我越来越不确定做得好。

3 个答案:

答案 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方法中释放它,就像保留属性一样。

总而言之,我建议你多学习一下这个:

  • 面向对象的编程(与您的问题无关,但我可以告诉您不习惯使用它。目标-C是面向对象的,因此您希望了解OOP)。
  • iOS内存管理。

答案 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。然后编译器会自动实现namesetName:,你不需要自己动手。

最后,您遗失了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