Setting an Objective-C class property without using a self reference

China☆狼群 提交于 2019-12-02 21:20:13

This would have also worked properly:

- (void)viewDidLoad {     
    stuff = [[NSArray alloc] initWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
}

Because the array was retained by alloc. But it's usually better to stick to the dot notation if you have a property and use the autorelease array creation methods, where you get retains "for free" from the property:

- (void)viewDidLoad {     
    NSArray *arr = [NSArray arrayWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
    self.stuff = arr;

}

You probably just left it out to keep things simple, but you also need to free this array in dealloc:

- (void)dealloc {     
  [stuff release]; stuff = nil;
}

When you use (self) and dot syntax, given the way you defined the property (nonatomic, retain), the NSArray (stuff) is retained.

When you don't, you are still making the assignment, but you aren't retaining the array aside from the implicit retain via alloc+init - and you release it right away.

You can get around assigning via "self.stuff = arr" by doing:

stuff = [arr retain];

But since you defined a property, you obviously WANT to be using dot syntax and having the retain called for you.

stuff = ... directly references the backing field of the property. It doesn't increase the retain count. As a result, releasing the object somewhere else might take its retain count down to zero and have it deallocated while you're still holding a reference to it. Also, it may cause a memory leak for the previous value of the property.
The reason it looks like working sometimes is that the object is probably not deallocated yet, by someone else.

On the other hand, self.stuff = ... will send a message to the property's set accessor which will take care of retain count.

The difference between doing:

stuff=arr;

and

self.stuff=arr;

is that in the second case, you're actually calling the automatically-synthesized setStuff: accessor method, which retains the array. In the code you've posted, the array is being created with alloc/initWithObjects, so it already has a retain count of 1.

You just need to change remove the call to [arr release] in your viewDidLoad: method, and all will be well:

- (void)viewDidLoad {     
    NSArray *arr = [[NSArray alloc] initWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
    stuff = arr;
}

As you noticed, you can also "fix" this by using self.stuff. I'd recommend against doing that, since it obscures the meaning of the code, and adds additional work that's not needed in most cases. In general, I recommend not using the "self." syntax in your instance methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!