【问题标题】:EXC_BAD_ACCESS in UITableViewControllerUITableViewController 中的 EXC_BAD_ACCESS
【发布时间】:2009-04-03 08:07:35
【问题描述】:

我正在尝试使用 UITableViewController(视图的委托和数据源)来显示从 Plist 读取的简单表。 Plist 包含一个 NSDictionary,它本身包含几个 NSDictionary 对象,这些对象代表我的应用程序中使用的对象。

其余代码看起来像这样(简化):

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadObjectsFromPlist];
}

- (void)loadObjectsFromPlist {
    NSString *objectPlistFile = [[NSBundle mainBundle] pathForResource:@"Objects" ofType:@"plist"];
    NSDictionary *objectsDictionary = [NSDictionary dictionaryWithContentsOfFile:objectsPlistFile];

    objects = [[NSMutableArray alloc] init];
    NSEnumerator *objectEnumerator = [objectsDictionary objectEnumerator];
    NSDictionary *objectData;
    while(objectData = [objectEnumerator nextObject]) {
        [objects addObject:[MyObject objectFromDictionary:objectData]];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [objects count];
}

由于我没有使用任何部分,因此我在控制器的 numberOfSectionsInTableView 中返回 1

MyObject”的objectFromDictionary 方法将从NSDictionary 读取的数据分配给一个新对象。我也尝试过保留、复制等,但这并没有改变任何东西。

当我调用[objects count] 时,我在tableView:numberOfRowsInSection 中得到一个EXC_BAD_ACCESS。我尝试使用对象分配工具,但没有发现问题。我的 Plist 当前仅包含一个对象的数据。调试器为objects 属性显示红色的“1 个对象”,所以我认为这与问题有关。

【问题讨论】:

  • 需要注意的是,调试器中“1 个对象”变量的红色仅仅意味着它的值在应用程序上次活动时发生了变化。 (例如,添加或删除了某些内容。)
  • 啊,好的...谢谢您清除它。所以这与我的问题无关,对我来说更加神秘。
  • 可能只是一个转录错误,但你有 [object addObject: [MyObject...,它可能应该是 [objects addObject...
  • 是的,只是转录错误。

标签: iphone objective-c cocoa-touch


【解决方案1】:

为确保在适当的时间加载数据,请尝试延迟初始化:

- (NSArray *)objectsFromPlist {
    if (!objects) {
       ... // initialize once here
    }
    return objects;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[self objectsFromPlist] count];
}

【讨论】:

    【解决方案2】:

    如果调试器显示EXC_BAD_ACCESS 出现在[servers count],那么(假定的)ivar servers 是否已正确初始化?我在您的示例代码中没有找到任何对它的引用。

    【讨论】:

    • 哦,对不起。我忘了在我的文本中重命名它。我试图将代码减少到最低限度,并将变量名称更改为更通用。在我的真实项目中,该变量调用servers,但在我的问题代码示例中它的初始化类似于objects
    【解决方案3】:

    objects 是什么?你能显示你的头文件吗?它可能会让我更好地理解。另外,您是否尝试过将[super viewDidLoad] 放在[self loadObjectsFromPlist] 之后?这似乎是一个时间问题,或者objects 在您的一种方法中意外释放。

    【讨论】:

    • 尝试跳过你的 plist 加载,只放 objects = [[NSMutableArray alloc] init];在 [super viewDidLoad] 之前。如果解决了问题,则确认存在时间问题。
    • 对象是属性吗?我想知道对象是否真的被正确保留了。尝试将 plist 函数中的 alloc 行更改为 objects = [[[NSMutableArray alloc] init]retain];
    【解决方案4】:

    我的猜测是您可能必须发布整个(相关)代码,而不是精简版本。在不知道您在代码和 plist 中还可能在做什么的情况下,很难确定这一点……我们都只是在这里盲目射击(诚然,这在 SO 上并不罕见;-)

    【讨论】:

    • 这可能会更快地解决我的问题。我会努力记住这一点。 ;)
    【解决方案5】:

    听起来它在调用 loadObjectsFromPlist 之前调用了 numberOfRowsInSection。

    如果您以编程方式加载控制器,可以尝试从 initWithFrame:Style: 调用 loadObjectsFromPlist,而不是 viewDidLoad。

    如果我面前有一个 mac,我会自己做,但您可能想尝试设置断点并弄清楚这些方法的调用顺序。整个地方的 NSLog 语句也可以工作。

    【讨论】:

    • 我已经用调试器检查过了。就像之前所说的,调试器甚至显示从 Plist 加载的数据(虽然是红色的)。
    【解决方案6】:

    您可能已经解除了UITableViewController 的分配,这意味着objects 成员不再有效。确保您在某处持有对UITableViewController 的引用。检查是否是这种情况的一种简单方法是在您的viewDidLoad 方法中添加一个[self retain] 调用(暂时!)。如果这让问题消失了,那么您需要仔细检查谁拥有控制器并确保他们没有释放它。

    编辑:我想更好的测试方法是在你的 dealloc 方法中放置一个断点。

    【讨论】:

    • 那行不通。 viewDidLoad 中的 [self retain] 仍然会崩溃。
    • 我在对象的 dealloc 中添加了一个断点...它从未被调用过。
    【解决方案7】:

    将 [self loadObjectsFromPlist] 放在 [super viewDidLoad] 之前。 您的“对象”变量从未初始化,这就是您收到 EXEC_BAD_ACCESS 错误的原因。

    【讨论】:

    • 这在 Jesse Brown 之前已经提到过,但是没有用。
    【解决方案8】:

    好的,在阅读了你所有的答案并试图找出我的错误之后,我几乎完全重写了我的代码。 最后,我删除了第一次发生错误时添加的调试输出。

    NSLog(@"Object count: %@", [objects count]);
    

    由于NSArraycount 不返回一个对象而是一个整数,这显然是错误的,应该是:

    NSLog(@"Object count: %u", [objects count]);
    

    尽管如此EXC_BAD_ACCESS 之前没有此行,但它似乎减慢了我的调试速度。 ;) 遗憾的是,我现在无法重现真正的问题。

    我能说的:该错误不是时间问题的结果。我现在仔细检查了。

    【讨论】:

    • 当您获得 EXC_BAD_ACCESS 时,转到控制台并键入“bt”以获取堆栈跟踪。可能对你有用,也对试图帮助你的人有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    相关资源
    最近更新 更多