我正在尝试使用我的UITableViewController的子类EXC_BAD_ACCESS

时间:2011-08-28 03:28:05

标签: iphone objective-c ios cocoa-touch

我正在尝试合并和修改WWDC 2010 vol128 Mastering Table Views中的扩展部分标题。但是,我一定错过了一步或忘了一些东西,因为当我尝试使用表视图访问我的视图时,我收到了EXC_BAD_ACCESS错误。

我忘了你可以在哪里找到源代码,但它在他们的开发者网站上。发布的代码很多。

我看到的主要区别是他们的版本将UITableViewController的子类作为子视图添加到他们的appdelegate即。窗口。我想将我的控制器添加到我在视图控制器中的scrollview。我确定因此存在问题?

下面的原文对我没有意义,因为它在将它添加为子视图之前释放了aTableViewController,在我的版本中我无法做到。它还使self.tableViewController = aTableViewController; tableViewController在顶部合成如下: @synthesize tableViewController=tableViewController_我不知道它来自哪里,因为它没有被引用到项目的任何其他地方。再次,原始代码在app代理中有这个代码,所以也许我不知道会发生什么事情。

Apple的代码(可行):

 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];

出于测试目的,我创建了一个空的testTableViewController子类,它实际上是空的,并尝试将其添加为具有相同结果的子视图。也许,我正在错误地创建一个UITableViewController子类。对不起,因为含糊不清,但我认为它与上面给出的一小部分信息有关。

由于

2 个答案:

答案 0 :(得分:0)

视图控制器不会被其视图保留;除其他原因外,这可以防止循环引用,这将导致解除分配问题。 :]您必须自己保留视图控制器。如果您声明的属性(self.tableViewController)没有保留VC,您将视图添加到窗口,但VC(视图的一组事件的委托!)将被取消分配,然后您将随机获得EXC_BAD_ACCESS。

您在问题中包含的代码看起来就像在您将视图添加到窗口之前将取消分配VC。我猜你通过修复该属性以确保VC被保留来消除崩溃。

答案 1 :(得分:0)

回答这个问题:

  

下面的原文对我没有意义,因为它释放了   aTableViewController在添加为子视图之前

你提到了:

  

它还使self.tableViewController = aTableViewController;该   tableViewController在顶部合成如下:@synthesize   tableViewController = tableViewController_我不知道它来自哪里   因为它没有在项目的任何其他地方引用。

最有可能的是,如果查看头文件,您会看到如下所示的行:

@property (nonatomic, retain) tableViewController;

这是Objective-C中的“声明属性”。声明的属性提供了一种超常方便的方法来获取/设置具有常见模式的ivars(例如保留分配给它们的任何值)。

来自文档:

  

Objective-C声明的属性功能提供了一种简单的方法   声明并实现一个对象的访问器方法。

你一定要阅读这里的介绍文档:

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

属性以经过验证的方式包含了一堆常见模式。

例如,考虑某人(天真)潜在的setter方法实现,该方法会自动保留分配给它的值:

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

乍一看似乎没问题,但请考虑以下代码段:

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

(稍后,可能在某些其他方法中,foo与上面的foo相同):

4: [bar setSomeIvar:foo];

这会发生什么?好吧,在第1行,保留计数为+1,在第2行,它是+2,第3行,第1行,然后,在第4行,我们无意中释放了对象,然后我们将它分配给了ivar并保留了它,所以这段代码会在该行上出错。

更正确的代码如下:

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

然而,这些模式甚至超越了这个简单的例子。

因此,属性非常方便,并将所有这些复杂性包含在比其他方式更可靠和可读的内容中。

它们还可以更加轻松地确保您发布了dealloc方法中应该包含的所有内容。只需查看标记为(... retain ...)的所有属性的头文件,并确保它们已在dealloc中发布。此外,特别是UIViewController及其子类,标有IBOutlet的任何保留属性都应设置为nil中的viewDidUnload

当我第一次开始使用Objective-C时,我并没有真正使用属性 - 我为此感到痛苦。一旦我理解了它们并开始使用它们,它们就会让我的生活更轻松。