Setting a property of the Objective-C class without using a self-reference

This morning, I ran into a crash in the iPhone app I’m working on, and while I fixed the error, I'm curious why the syntax reason was a problem.

Here is my code reduced to simple elements. I populate items in a TableView using NSArray for items. NSArray is a property:

@interface FooViewController : UITableViewController { NSArray *stuff; } @property (nonatomic, retain) NSArray *stuff; 

And in my implementation file:

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

Now, when I first wrote the method, I accidentally left the "I". and it caused a bomb. Although during testing it worked first to blush. I tried:

 stuff = arr; NSLog(@"%d", [stuff count]); 

But using material in other methods of bombardment. Now that I have fixed the problem, I can use [number of pieces] in other places.

So why can I use material in some places, but in others should I use self.stuff ?

+6
objective-c
source share
4 answers

This would also work correctly:

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

Since the array was saved using alloc. But it’s usually best to stick with dot notation if you have a property and use the autorelease array creation methods, where you get “free” from the property:

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

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

 - (void)dealloc { [stuff release]; stuff = nil; } 
+4
source share

When you use (self) and dotted syntax, given how you defined the property (non-atomic, save), the NSArray (material) is saved.

If you don’t do this, you still do the job, but you don’t save the array aside from implicit saving through alloc + init - and you immediately release it.

You can bypass the assignment via self.stuff = arr by doing:

 stuff = [arr retain]; 

But since you defined the property, you obviously WANT to use the point syntax and have a call for you.

+5
source share

stuff = ... directly refers to the property support field. This does not increase the number of deductions. As a result, releasing the object elsewhere can cause its count to be kept to zero and release it while you still hold the link to it. In addition, this may lead to a memory leak for the previous property value.
The reason, apparently, is that sometimes it works that the object is probably not yet released, by someone else.

self.stuff = ... , self.stuff = ... other hand, self.stuff = ... send a message to the accessory of the property set, which will take care of holding the account.

+3
source share

The difference between the execution:

 stuff=arr; 

and

 self.stuff=arr; 

is that in the second case, you are actually calling the automatically-synthesized setStuff: accessor method, which saves the array. In the code you posted, the array is created using alloc / initWithObjects, so it already has a storage counter of 1.

You just need to change the call deletion to [arr release] in your viewDidLoad: method and everything will be fine:

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

As you noticed, you can also "fix" this using self.stuff. I would recommend not to do this, because it hides the meaning of the code and adds extra work, which is not needed in most cases. In general, I do not recommend using "I". The syntax in your instance methods.

+3
source share

All Articles