2012-11-03 127 views
1

首先,請原諒我的英語。UITableView應用程序在滾動時崩潰

我正在學習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; 
+1

我建議從Xcode菜單運行產品 - >分析並修復它報告的任何問題。我相當肯定你不應該在'cellForRowAtIndexPath:'中釋放'member',但我不知道是否有其他地方。 (另外,考慮轉換爲ARC。) –

+2

您是否通過'[self configureCell:cell withFamilyMember:member]保留了'member';'所以您必須釋放它? –

+0

你不擁有'member',不要釋放它 – yfrancis

回答

1

此行不遞增保留計數: TMTFamily *member = [familyMembers objectAtIndex:indexPath.row]

所以下面一行是你的問題 [member release];

您無法釋放的對象,如果你down't擁有它。要麼保留它那樣: TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] retain];

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

或刪除completelly提到release

+0

在這裏沒有必要'retain',最好是擺脫'release'' – yfrancis

+0

刪除'code'[成員發佈]行我的應用程序仍然崩潰:( – TrieuMinhTien

+0

我希望你刪除第二[部件釋放],而不是一個在'loadMemberListFromDatabase'? –

1

首先,歡迎來到Stack Overflow,歡迎來到iOS開發的世界。

有一堆與你的代碼的問題,如果你有一個蘋果開發者賬號,我強烈建議你頭部到2012年的WWDC會議視頻,並期待在談論現代Objective C的會話。 https://developer.apple.com/videos/wwdc/2012/

看代碼,你的壞訪問既可以是已經釋放的對象或一個空單元格。要確定原因,你需要啓用NSZombies。要做到這一點,請點擊您的項目名稱在工具欄,如下所示:

enter image description here

在這個例子中,它被稱爲PartialTransparentcy(拼寫被定罪)。當你點擊那個按鈕時,點擊編輯方案按鈕,你會看到一個選項列表。你需要點擊啓用殭屍對象。如果您沒有看到它,請按診斷選項卡。

enter image description here

然後運行你的代碼,它會記錄這是給你的悲傷的對象。請記住,殭屍物件非常昂貴。如果您提交的應用已啓用,您將被自動拒絕。

,當我看着你的初始化代碼我注意到的第一件事情是這樣的:

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

您正在發送中,否定再利用細胞的整個整個點零標識符。相反,您正在爲每一行創建一個新的單元格,而不是重新使用較早的單元格。

所以取消這一行:

static NSString *MyIdentifier = @"MyIdentifier"; 

,改變出隊的方法來閱讀這樣的:

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

如果您正在構建在Interface Builder你的細胞,你需要也給該單元是一個標識符。這可能是事故的原因。

接下來...您的sqllite代碼應封裝在另一個對象中。視圖控制器沒有理由知道它。另外,你應該真正調查覈心數據。它默認爲sqllite支持存儲。這也是一個非常棒的技術。

最後,看看ARC。讓編譯器處理內存管理的煩人工作,以便您可以專注於應用程序的用戶體驗。

希望有所幫助,祝你好運!

+0

我想投票回答這個問題,因爲它非常友好!不幸的是,這很可能不是崩潰的原因,正如Tomasz所說,一個簡單的內存管理問題 – yfrancis

+0

感謝您的好意:D啓用殭屍對象後,我收到消息意味着我正在嘗試訪問有限的內存。 – TrieuMinhTien

+0

我也嘗試將sqlite代碼移動到AppDelegate類,但沒有固定,我的應用程序仍然崩潰:( – TrieuMinhTien