开发者

I'm getting EXC_BAD_ACCESS trying to use my subclass of UITableViewController

I'm trying to incorporate and modify the expanding section headers from WWDC 2010 vol128 Mastering Table Views. However, I must have missed a step or forgot something because I'm getting the EXC_BAD_ACCESS error when I try to access my view with the table view.

I forget where you can find the source code, but it's on their developer website. It's a lot of code to post.

The main difference I see is that their version adds the subclass of UITableViewController as a subview to their appdelegate ie. window. I want to add my controller to my scrollview which is in a viewcontroller. I'm sure there is an issue because of that?

The original below makes no sense to me because it releases the aTableViewController before adding it as a subview, which in my version I cannot do. It also makes self.tableViewController = aTableViewController; the tableViewContr开发者_开发百科oller is synthesized at the top like this: @synthesize tableViewController=tableViewController_ I dont know where it comes from since it is not referenced anywhere else in the project. Again, the original had this code in the app delegate, so maybe there's something I dont know that is going on there.

Apple's code (it works):

 TableViewController* aTableViewController = [[TableViewController alloc] initWithStyle:UITableViewStylePlain];
    aTableViewController.plays = self.plays;
    self.tableViewController = aTableViewController;
    [aTableViewController release];

    // Stamdard window display.
    [self.window addSubview:aTableViewController.view];
    [self.window makeKeyAndVisible];

For testing purposes, I made an empty testTableViewController subclass which is virtually empty, and tried to add it as a subview with the same outcome. Perhaps, I'm creating a UITableViewController subclass incorrectly. Sorry, for being vague, but I think it has something to do with the snippet of information given above.

Thanks


To answer this:

The original below makes no sense to me because it releases the aTableViewController before adding it as a subview

You mentioned:

it also makes self.tableViewController = aTableViewController; the tableViewController is synthesized at the top like this: @synthesize tableViewController=tableViewController_ I dont know where it comes from since it is not referenced anywhere else in the project.

Most likely, if you look in the header file, you'll see a line like this:

@property (nonatomic, retain) tableViewController;

This is a "Declared Property" in Objective-C. Declared properties provide a super-convienient way of getting/setting ivars with common patterns (such as retaining any value assigned to them).

From the documentation:

The Objective-C declared properties feature provides a simple way to declare and implement an object’s accessor methods.

You should definitely read the introduction documentation here:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

Properties wrap up a bunch of common pattern in tried-and-true ways.

For example, consider someone's (naive) potential implementation of a setter method which automatically retains the value assigned to it:

- (void) setSomeIvar:(SomeObject *)value
{
     [ivarValue release];
     ivarValue = [value retain];
}

This seems OK upon first glance, but consider the following code snippet:

1: SomeObject * foo = [SomeObject new];
2: [bar setSomeIvar:foo];
3: [foo release];
...

(later, potentially in some other method, where foo is the same foo as above):

4: [bar setSomeIvar:foo];

What would happen here? Well, in line 1, the retain count is +1, in line 2, it's +2, line 3, +1, then, later, in line 4, we inadvertently released the object before we assigned it to the ivar and retained it, so this code would error on that line.

The more-correct code would be something like:

- (void) setSomeIvar:(SomeObject *)value
{
     if (ivarValue == value) return;
     [ivarValue release];
     ivarValue = [value retain];
}

However, the patterns move beyond even this simplistic example.

So, properties are super convenient, and wrap up all this complexity into something more reliable and readable than otherwise possible.

They also make it much easier to make sure you're releasing everything you're supposed to be in your dealloc method. Simply look at the header file for all properties marked (...retain...) and make sure they're getting released in the dealloc. Also, for UIViewControllers in particular, and their subclasses, any retained properties marked with IBOutlet should be set to nil in viewDidUnload.

When I first started using Objective-C I didn't really use properties - and I suffered for it. Once I understood them and started using them they made my life MUCH easier.


View controllers are not retained by their views; among other reasons, this prevents circular references which would make deallocation problematic. :] You have to retain the view controller yourself. If the property you declared (self.tableViewController) isn't retaining the VC, you'll add the view to the window but then the VC (the view's delegate for a bunch of events!) will get deallocated, and then you'll get random EXC_BAD_ACCESS.

The code you included in your question looks like your VC would get deallocated before you even added the view to the window. I'm guessing you got rid of the crash by fixing that property to ensure that the VC is being retained.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜