2013-07-02 60 views
1

我創建了一個表格視圖作爲我學校的一個應用程序的一部分,它允許學生進入他們的作業,然後檢查它並使其消失,就像提醒應用程序一樣。我遇到的問題是,當我檢查一行以使其消失時,我從表中刪除該行,並使用其存儲所有HomeworkItem s的數組中的數據從HomeworkItem中刪除該行;但是,下次嘗試添加一行(通過單擊最後一行的緩衝區行)時,添加的新行與剛刪除的行相同,即使HomeworkItem已從該行中刪除陣列。我記得讀過NSableViews嘗試重複使用行以提高內存效率,但我不明白爲什麼這行會掛在舊信息上。有人可以解釋爲什麼會發生這種情況,或者我可以如何解決它?NSTableView重複使用舊數據行

這裏是我的自定義代碼TableViewCell:

HomeworkTableViewCell.h:

#import <Cocoa/Cocoa.h> 
#import "AppDelegate.h" 
#import "ClassViewController.h" 

@class ClassViewController; 
@class AppDelegate; 

@interface HomeworkTableCellView : NSTableCellView 

@property (weak) IBOutlet NSTextField *assignmentName; 
@property (weak) IBOutlet NSDatePicker *dueDatePicker; 
@property BOOL isCompleted; 
@property NSInteger rowNumber; 
@property (weak) AppDelegate *ad; 
@property NSTableView *superTable; 
@property ClassViewController *superCVC; 

- (void)setSuperRow:(id)sender; 
- (IBAction)completed:(id)sender; 
- (IBAction)dateChanged:(id)sender; 

@end 

HomeworkTableViewCell.m:

#import "HomeworkTableCellView.h" 

@implementation HomeworkTableCellView 

- (id)initWithCoder:(NSCoder *)aDecoder{ 
// NSLog(@"I");//TEST 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     self.ad = [[NSApplication sharedApplication]delegate]; 
     self.superTable = self.ad.classViewController.homeworkTable; 
     self.superCVC = self.ad.classViewController; 
     self.isCompleted = NO; 
    } 
    return self; 
} 

- (void)setSuperRow:(id)sender{ 
    [self.superCVC updateRow:sender]; 
} 
- (IBAction)completed:(id)sender{ 
    self.isCompleted = !self.isCompleted; 
    [self.superCVC changeStateOfHomeworkItem:self]; 
    [self.superCVC updateRow:sender]; 
} 
- (IBAction)dateChanged:(id)sender{ 
    [self.superCVC updateRow:sender]; 
    [self.superCVC editDateOfHomeworkItem]; 
} 
@end 

這裏正在發生的問題的視頻的鏈接:http://youtu.be/Ot8w5oz8L-E

控制檯中的文本是在刪除一個對象之後,在家庭作業數組中表示什麼,所以很明顯,刪除的對象不再存在。

編輯: 這就是我想出了利用UASI的建議:

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 
{ 
    HomeworkTableCellView *HTCV = [self.homeworkTable makeViewWithIdentifier:tableColumn.identifier owner:self];//maybe owner:nil 
    [HTCV.assignmentName setStringValue: @""]; 
    [HTCV.dueDatePicker setDateValue: [[NSDate alloc]initWithString:@"1-1-1 0:0:0 +0000"]];//false date for testing 
    HTCV.isCompleted = NO; 
    [HTCV.checkBox setState:NSOffState]; 

    [self updateTableView]; 

    return HTCV; 
} 

- (void)updateTableView{ 
    for (int i = 0; i < self.ad.currentSubject.homework.count; i++) { 
     HomeworkTableCellView *HTCV = [self.homeworkTable viewAtColumn:0 row:i makeIfNecessary:NO]; 
     HomeworkItem *HI = [self.ad.currentSubject.homework objectAtIndex:i]; 
     [HTCV.dueDatePicker setDateValue: HI.dueDate]; 
     [HTCV.assignmentName setStringValue: HI.details]; 
    } 
} 
+1

該視頻似乎是私人的:/ – uasi

+0

我的壞,現在公開! –

+1

請注意,tableView:viewForTableColumn:row:是NSTableViewDelegate的一部分,而不是NSTableViewDataSource。因此,確保任何對象實現該方法是表視圖的代表(和數據源)。 – zpasternack

回答

4

你可能不使用-tableView:objectValueForTableColumn:row:使表格單元格的意見。儘管文檔聲稱「此方法是強制性的」,但在<AppKit/NSTableView.h>中發現的方法的評論說'這種方法對於「基於單元的」表格視圖是必需的,並且對於「基於視圖」的表格視圖是可選的。

相反,你可以使用NSTableViewDelegate-tableView:viewForTableColumn:row:方法:

- (NSView *)tableView:(NSTableView *)tableView 
    viewForTableColumn:(NSTableColumn *)tableColumn 
        row:(NSInteger)row 
{ 
    // Instantiate a view object from XIB or reuse one in the cache. 
    NSString *identifier = @"YOUR_CELL_VIEW_IDENTIFIER"; 
    HomeworkTableCellView *HTCV = [tableView makeViewWithIdentifier:identifier owner:nil]; 

#if 0 
    // If you have not put a HomeworkTableCellView object in a XIB with identifier, 
    // you'll need to create an instance programatically like this; 
    // It seems not to be the case, though. 
    if (HTCV == nil) { 
    HTCV = [[HomeworkTableCellView alloc] initWithFrame:NSZeroRect]; 
    HTCV.identifier = identifier; 
    } 
#endif 

    // Do initialization anything specific to a row here, 
    // because the view's -init{WithCoder:,WithFrame:} method 
    // is not always called for each row due to the cache mechanism. 
    HomeworkItem *HI = [self.homeworkArray objectAtIndex:row]; 
    [HTCV.dueDatePicker setDateValue: HI.dueDate]; 
    // ... 

    return HTCV; 
} 
+0

感謝您的信息,我會試試這個。儘管如此,我最後回顧的觀點是什麼?它只是HTCV,還是我需要創造不同的東西? (我對此很新,並且在所有不同視圖上都不是100%可靠) –

+0

對不起,那個'view'是一個錯字。修復了答案。 – uasi

+0

出於某種原因,'-tableView:viewForTableColumn:row:'不適合我。它甚至沒有被調用。這是一個基於視圖的表,所以我不知道爲什麼。我已經用我爲該方法嘗試做的事情更新了原始帖子。 –

2

我知道這個問題是有點老了,但我只是把它在那裏的人喜歡,我自己,在尋找一個辦法。

if ([self.tableView respondsToSelector:@selector(usesStaticContents)]) 
    //Method currenly only available on OS X 10.10 or later 
    { 
    //This is used to prevent table view rows from being reused 
    /*From:https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/ 
     Normally, a table view will only keep around a subset of the total number of rows potentially available (in general, this is limited to the visible region, plus some overdrawn allowance for responsive scrolling). A static table view keeps all views added to the table around when usesStaticContents=YES 
     */ 
     //Also check out: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TableView/TableViewOverview/TableViewOverview.html 

    self.tableView.usesStaticContents = YES; 

    } 

注意:您的應用程序可以通過使用該解決方案(原因很明顯),表現出更高的內存利用率。然而,在我的測試中,這並沒有太大的區別,你的里程可能會有所不同。

+0

我甚至不能相信這實際上有效...... –

相關問題