tags:

views:

67

answers:

2

I got nabbed by the following bug again and would like some clarification to exactly why it is a bug.

I have a simple UITableView that loads some data:

// myclass.h
@property (nonatomic, retain) NSArray *myData

// myclass.m
@synthesize myData;

- (void) viewDidLoad {
  ...
  myData = someDataSource // note the lack of self
}

- (UITableViewCell *) cellForRowAtIndexPath ... {
   ...
   cell.textLabel.text = [self.myData objectAtIndex:indexPath.row];  // EXC_BAD_ACCESS
}

The table first loads fine, but when scrolling up enough that one of the cells is totally out of the view I then get the EXC_BAD_ACCESS error.

Am I missing something in regards to @property retain. My understanding is that it releases anything that the pointer was previously pointing to before the reassignment. If I am correct then why would not using self. cause any problems?

Thanks for the help.

** Update

Why is is that in all the examples that I have checked with to the release of objects within the dealloc method without the self?

- (void) dealloc { 
  [someArray release]; 
  [someTableView release];
}
+1  A: 

If you don't use self., you are directly assigning to the instance variable myData, which has nothing to do with the property myData.

self.myData is just syntactic sugar for [self myData] or [self setMyData:newValue], and the synthesized property just creates the -myData and -setMyData: methods.

The instance variable is just a variable, nothing more. While it may have the same name, assigning to it or reading from it it is just like accessing any variable: nothing is retained, released, or in other ways modified besides the assignment.

chpwn
I realize they are methods, but are they not just wrappers around the myData variable?I guess the question is why does myData = ... get lost?
chris
@chris, you have to call the method for the `retain` to happen - you are putting an end run on the system by not having `self.` in there.
Carl Norum
Not really, Carl. They aren't wrapping it, they are specifying an interface to it. And that interface happens to retain and release what you give it. But assignment to variables doesn't. Think about this way: variables are in C, so assignment works just as in C, nothing more. But messages aren't, so they can do more than what's in C.
chpwn
@carl, like you said if I use myData = ...; [myData retain]; it does work as well. I guess what I find confusing is why do things run fine when the tableView is bound the first time through.
chris
self... is missing from dealloc because there's no guarantee that the accessor methods are still available at that point in the dealloc function.
blindJesse
@blindJesse, thanks for that info. If that is the case I am assuming these methods would also cause for the same error to occur if the object had not been retained up to that point, although the error might go unnoticed.
chris
It could cause the same error. Sending a release message to an object that already has a retain count of 0 could as well (this is a more common problem I've experienced in dealloc methods). See http://stackoverflow.com/questions/1505232/dot-notation-dealloc too.
blindJesse
+1  A: 

In case of

myData = someDataSource;

you are giving the reference of someDataSource (a local variable or limited scope variable) to myData. Now as soon as someDataSource goes out of scope it gets released and as you have passed its reference to myData it also gets released.

now in the case of

self.myData = someDataSource;

the value of someDataSource is assigned to myData. Hence whatever happens to someDataSource myData will retain the value.

You can also do it otherwise:

myData = [someDataSource retain];

Hope this helps.

Thanks,

Madhup

Madhup