【问题标题】:UITableView application crashes when scrollingUITableView 应用程序在滚动时崩溃
【发布时间】:2012-11-03 15:21:00
【问题描述】:

首先,请原谅我的英语。

我正在学习 iPhone SDK、Obj-C 并尝试制作 UITableView 应用程序。但是滚动表格时我的应用程序崩溃了。我已经搜索但无法解决我的问题,所以我在这里发布我的问题并寻求您的帮助。

TMTMemberListTableViewController.h

@interface TMTMemberListTableViewController : UITableViewController
{
    NSMutableArray *familyMembers;
    sqlite3 *database;
}

@property (nonatomic, retain) NSMutableArray *familyMembers;

- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member;

@end

TMTMemberListTableViewController.m

@interface TMTMemberListTableViewController (Private)
    - (void) loadMemberListFromDatabase;
@end

@implementation TMTMemberListTableViewController

@synthesize familyMembers;

- (void) loadMemberListFromDatabase
{
    familyMembers = [[NSMutableArray alloc] init];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"easycook.sqlite"];
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
    {
        const char *sql = "SELECT member_id from family";
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK)
        {
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *memberID = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)];
                TMTFamily *member = [[TMTFamily alloc] initWithMemberID:memberID database:database];
                [familyMembers addObject:member];
                [member release];
            }
        }
        sqlite3_finalize(statement);
    }
    else
    {
        sqlite3_close(database);
        NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.clearsSelectionOnViewWillAppear = NO;

    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    [self loadMemberListFromDatabase];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [familyMembers count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //static NSString *MyIdentifier = @"MyIdentifier";

    TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];
    if (cell == nil)
    {
        cell = [[[TMTFamilyMemberCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    TMTFamily *member = [familyMembers objectAtIndex:indexPath.row];
    // Set up the cell
    [self configureCell:cell withFamilyMember:member];
    [member release];
    return cell;
}

- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member
{
    cell.familyMember = member;
    cell.memberNameLabel.text = member.description;
}
- (void)dealloc
{
    NSLog(@"Dealloc");
    [familyMembers release];
    [super dealloc];
}

滚动表格时,我的应用程序在

处因 EXC_BAD_ACCESS 而崩溃
[self configureCell:cell withFamilyMember:member];

cell.memberNameLabel.text = member.description;

【问题讨论】:

  • 我建议从 Xcode 菜单运行 Product->Analyze 并修复它报告的任何问题。我有理由确定你不应该在cellForRowAtIndexPath: 中发布member,但我不知道是否还有其他类似的地方。 (另外,考虑转换为 ARC。)
  • 你是不是member[self configureCell:cell withFamilyMember:member];保留所以你必须释放它?
  • 你不拥有member,不要发布它

标签: iphone ios sqlite uitableview nsmutablearray


【解决方案1】:

这一行没有增加保留计数器: TMTFamily *member = [familyMembers objectAtIndex:indexPath.row]

所以下面这行是你的问题 [member release];

如果你不拥有它,你就不能释放它。要么像这样保留它: TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] retain];

TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] copy];

或完全删除提及的release

【讨论】:

  • 这里不需要retain,最好去掉release
  • 删除 'code'[member release] 行后,我的应用程序仍然崩溃:(
  • 我希望你删除了第二个 [member release] 而不是 loadMemberListFromDatabase 中的那个?
  • 您是否将MyIdentifier 传递给dequeueReusableCellWithIdentifier?现在哪里崩溃了?请为所有异常添加通用断点以查看它。
  • 最后,我修复了我的错误。我的错误不在此处发布的两个文件中,而是在我的 TMTFamily 类的 init() 方法中。为 description 属性设置值时,我不使用 self.description,而是直接为 description 赋值。感谢您的帮助:)
【解决方案2】:

首先,欢迎来到 Stack Overflow,欢迎来到 iOS 开发世界。

您的代码存在很多问题,如果您有 Apple 开发者帐户,我强烈建议您前往 2012 WWDC 会议视频并查看有关 Modern Objective C 会议的讨论。 https://developer.apple.com/videos/wwdc/2012/

查看代码,您的错误访问可能是已释放的对象或空单元格。要确定原因,您需要启用 NSZombies。为此,请在工具栏中单击您的项目名称,如下所示:

在这个例子中,它被称为 PartialTransparentcy(拼写该死)。当您单击该按钮时,单击编辑方案按钮,您将看到一个选项列表。您需要单击启用僵尸对象。如果您没有看到它,请按“诊断”选项卡。

然后运行您的代码,它会记录让您感到悲伤的对象。请记住,僵尸对象非常昂贵。如果您提交启用它们的应用程序,您将被自动拒绝。

当我查看您的单元初始化代码时,我首先注意到的是:

TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];

您正在发送一个 nil 标识符,它否定了重用单元格的整个要点。相反,您正在为每一行创建一个新单元格,而不是重用旧单元格。

所以取消注释这一行:

static NSString *MyIdentifier = @"MyIdentifier";

并将 dequeue 方法更改为如下所示:

TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];

如果您在界面生成器中构建单元格,您还需要为单元格指定一个标识符。这可能是坠机的原因。

下一步...您的 sqllite 代码应该封装在另一个对象中。视图控制器没有理由知道它。此外,您应该真正调查核心数据。它默认为 sqllite 后备存储。这也是一项非常棒的技术。

最后,看看 ARC。让编译器处理繁琐的内存管理工作,这样您就可以专注于应用程序的用户体验。

希望对您有所帮助,祝您好运!

【讨论】:

  • 我想为这个答案投票,因为它非常友好!不幸的是,这可能不是崩溃的原因,正如 Tomasz 所说,这是一个简单的内存管理问题
  • 感谢您的好意 :D 启用僵尸对象后,我收到消息意味着我正在尝试访问已释放的内存。
  • 我也尝试将 sqlite 代码移动到 AppDelegate 类,但没有任何修复,我的应用程序仍然崩溃:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2012-12-07
  • 2018-01-16
  • 2016-08-28
  • 1970-01-01
  • 2011-07-10
  • 2011-12-26
相关资源
最近更新 更多