1

学校のアプリの一部としてテーブル ビューを作成しました。このアプリを使用すると、リマインダー アプリと同じように、生徒が宿題を入力してチェックを入れて消すことができます。私が直面している問題は、行をチェックして非表示にするときに、その行をテーブルから削除し、すべてのsHomeworkItemを保持する配列からそのデータを削除することです。HomeworkItemただし、次に行を追加しようとすると (最後にバッファー行をクリックして)、追加された新しい行は、配列から削除されていてHomeworkItemも、削除したばかりの同じ行であり、同じ情報を持っています。HomeworkItemNSableViews が行を再利用してメモリを効率的に使用しようとしていると読んだことを覚えていますが、行が古い情報にぶら下がっている理由がわかりません。

カスタム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];
    }
}
4

2 に答える 2

4

-tableView:objectValueForTableColumn:row:テーブル セル ビューの作成には使用しない場合があります。このドキュメントでは「このメソッドは必須です」と主張していますが、<AppKit/NSTableView.h>「このメソッドは「セル ベース」の TableView では必須であり、「ビュー ベース」の TableView ではオプションです」というコメントが見つかりました。

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;
}
于 2013-07-02T08:40:09.327 に答える
1

私はこの質問が少し古いことを知っていますが、解決策を探していた私のような人々のためにそこに出しています.

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;

   }

注: このソリューションを使用すると、アプリのメモリ使用率が高くなる場合があります (明らかな理由により)。ただし、私のテストでは大きな違いはありませんでした。走行距離は異なる場合があります。

于 2015-10-27T05:27:21.047 に答える