首先,请原谅我的英语。
我正在学习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;
答案 0 :(得分:1)
此行未递增保留计数器:
TMTFamily *member = [familyMembers objectAtIndex:indexPath.row]
以下是您的问题
[member release];
如果您不拥有它,则无法释放对象。要么保留它:
TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] retain];
或
TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] copy];
或完全删除提及的release
。
答案 1 :(得分:1)
首先,欢迎来到Stack Overflow,欢迎来到iOS开发世界。
您的代码存在许多问题,如果您有Apple开发人员帐户,我强烈建议您前往2012 WWDC会话视频并查看有关Modern Objective C会话的讨论。 https://developer.apple.com/videos/wwdc/2012/
查看代码,您的错误访问可能是已发布的对象或空单元格。要确定原因,您需要启用NSZombies。为此,请单击工具栏中的项目名称,如下所示:
在这个例子中,它被称为PartialTransparentcy(拼写被诅咒)。单击该按钮时,单击编辑方案按钮,您将看到一个选项列表。您需要单击启用Zombie对象。如果看不到,请按“诊断”选项卡。
然后运行你的代码,它会记录给你悲伤的对象。请记住,僵尸对象非常昂贵。如果您提交的应用已启用,则系统会自动拒绝您。
当我查看您的单元格初始化代码时,我注意到的第一件事是:
TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];
您正在发送一个nil标识符,该标识符否定了重用单元格的整个点。相反,您要为每一行创建一个新单元格,而不是重用较旧的单元格。
因此取消注释:
static NSString *MyIdentifier = @"MyIdentifier";
并将dequeue方法更改为如下所示:
TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
如果要在界面构建器中构建单元格,则还需要为单元格指定标识符。这可能是导致坠机的原因。
下一步...你的sqllite代码应封装在另一个对象中。视图控制器没有理由知道它。此外,您应该真正调查核心数据。它默认为sqllite后备存储。这也是一项非常棒的技术。
最后,看看ARC吧。让编译器处理内存管理的繁琐工作,以便您可以专注于应用程序的用户体验。
希望有所帮助,祝你好运!