目标C - 添加一个新行以清空NSTableView

时间:2013-02-21 14:22:41

标签: objective-c macos cocoa nstableview

我有一个基于视图的NSTableView,它最初应为空。我还有“添加”和“删除”按钮,用于在同一个NSTableView中添加和删除行。

我添加新行的委托方法和方法如下所示:

#import "PreferencesApiKeysViewController.h"
#import "UserKeys.h"

@interface PreferencesApiKeysViewController ()

@property (weak) IBOutlet NSTableView *keysTableView;

@end

@implementation PreferencesApiKeysViewController
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // Get a new ViewCell
    NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];

    if([tableColumn.identifier isEqualToString:@"userKeysColumn"]) {
        UserKeys *allKeys = [self.allKeys objectAtIndex:row];
        cellView.textField.stringValue = allKeys.userKeyName;
        return cellView;
    }
    return cellView;
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    NSLog(@"Initial rows: %li", (unsigned long)[self.allKeys count]);
    return [self.allKeys count];
}

- (IBAction)addKey:(id)sender {
    UserKeys *newKey = [[UserKeys alloc] initWithKeyName:@""
                                                   apiID:@""
                                                 apiCode:@"" ];

    [self.allKeys addObject:newKey];
    NSLog(@"Total rows: %li", (unsigned long)self.allKeys.count);
    NSInteger newRowIndex = self.allKeys.count;
    if (newRowIndex == 0) {
        NSLog(@"No rows.");
        newRowIndex = 0;
    } else {
        NSLog(@"Has rows.");
        newRowIndex = self.allKeys.count-1;
    }
    NSLog(@"New Index: %ld", (long)newRowIndex);

    [self.keysTableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:newRowIndex] withAnimation:NSTableViewAnimationSlideDown];

    [self.keysTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:newRowIndex] byExtendingSelection:NO];
    [self.keysTableView scrollRowToVisible:newRowIndex];
}

@end

在我的AppDelegate.m中,我正在调用我的观点:

#import "AppDelegate.h"
#import "UserKeys.h"
#include "PreferencesApiKeysViewController.h"

@interface  AppDelegate()
@property (nonatomic,strong) IBOutlet PreferencesApiKeysViewController *prefsViewController;
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    self.prefsViewController = [[PreferencesApiKeysViewController alloc] initWithNibName:@"PreferencesApiKeysViewController" bundle:nil];

    // Create few rows as dummy data
    /*
    UserKeys *key1 = [[UserKeys alloc] initWithKeyName:@"key one"
                                                 apiID:@"123"
                                               apiCode:@"xxx" ];

    UserKeys *key2 = [[UserKeys alloc] initWithKeyName:@"key two"
                                                 apiID:@"456"
                                               apiCode:@"yyy" ];
    NSMutableArray *tempKeys = [NSMutableArray arrayWithObjects:key1, key2, nil];
    self.prefsViewController.allKeys = tempKeys;
    */
    // done.

    [self.window.contentView addSubview:self.prefsViewController.view];
    self.prefsViewController.view.frame = ((NSView*)self.window.contentView).bounds;
}

@end

现在,这里的问题是,如果我取消注释那些在AppDelegate中添加虚拟数据并启动我的应用程序的几行,一切正常。我可以毫无问题地添加/删除行,我甚至可以删除所有行并在此之后添加一个新行。

但是,如果我再次评论这些行,我的应用程序以空表开始(这是我需要的),当我想添加新行时,我收到错误:

*** Assertion failure in -[NSTextFieldCell _objectValue:forString:errorDescription:], /SourceCache/AppKit/AppKit-1187.34/AppKit.subproj/NSCell.m

进一步查看该主题,我看到只有一行引用了我的应用程序:

0x0000000100003116 -[PreferencesApiKeysViewController tableView:viewForTableColumn:row:] + 406

我猜我的TableView没有正确实例化,如果allKeys数组真的不包含任何单个对象,但我不确定如何解决这个问题?如何创建一个空的NSTableView,并且能够在单击“添加”按钮时自己添加第一行(不向allKeys添加任何虚拟数据)?

1 个答案:

答案 0 :(得分:2)

将此添加到PreferencesApiKeysViewController的实现中:

@implementation PreferencesApiKeysViewController

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
    if ((self = [super initWithNibName:nibName bundle:bundle])) {
        self.allKeys = [NSMutableArray array];
    }
    return self;
}

// add the following only if not using ARC
- (void)dealloc {
    [_allKeys release];
    [super dealloc];
}

@end

当您允许编译注释掉的代码时,您正在为NSMutableArray实例变量分配allKeys实例时发生的情况。因此,添加和删除项目的工作方式与您预期的一样。

通常,在这种情况下,管理NSMutableArray的类应覆盖init方法,以确保将数组正确初始化为空数组。 (默认情况下,非IBOutlet个实例变量初始化为nil,这样就无法正确添加或删除项目。