标签时NSTableView中的NSTokenFieldCell崩溃了,这是一个错误吗?

时间:2011-10-27 02:36:34

标签: objective-c cocoa nstableview nstokenfield

我遇到了NSTokenFieldCell的问题,所以我继续在Xcode中创建一个新项目以隔离问题。这是我做的:

  • 将NSTableView放入主窗口;
  • 选择第二列的文本单元格,并将其类别(通过Identity Inspector)更改为NSTokenFieldCell;
  • 使用以下代码实现了最小可能的数据源对象:

    - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
        return 1;
    }
    
    - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
        return @"aa, bb";
    }
    

起初它似乎工作正常,但是如果你双击要编辑的单元格,然后选项卡和shift + tab来来回切换单元格,最终当令牌字段单元格获得焦点时,应用程序会以BAD ACCESS崩溃

我在Lion 10.7.2中使用Xcode 4.2,其中包含Mac OS X Cocoa应用程序模板附带的所有默认设置。

2 个答案:

答案 0 :(得分:3)

看起来像Cocoa中的一个错误。如果你打开僵尸,你会看到:

2011-10-31 00:02:43.802 tokenfieldtest[35622:307] *** -[NSTokenFieldCell respondsToSelector:]: message sent to deallocated instance 0x1da761f10

我尝试为表设置委托并实现- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row,每次都返回一个新的NSTokenFieldCell(仅用于令牌列),但我得到了同样的错误。

答案 1 :(得分:0)

原来的解决方案带来了一个新问题。

NSTokenFieldCell未完全显示NSTableView时,进入编辑状态再退出会导致table view显示异常。

所以我反复尝试以获得更好的解决方案:

class MyTokenFieldCell: NSTokenFieldCell {
    override func fieldEditor(for controlView: NSView) -> NSTextView? {
        return nil;
    }
}

可能是NSTableViewNSTokenFieldCell的编辑器重用机制有问题,导致程序崩溃。

fieldEditorForView: 在这里被覆盖,返回nil,这样应该会导致每次编辑时都重新创建编辑器,避免复用,从而解决崩溃问题。


以下为原答案。

⚠️ 由于解决方案导致其他问题,请忽略。

我也遇到过这个问题。我的解决办法是暂时保留table view使用的cells。

  1. 自定义 NSTokenFieldCell:每次复制后,临时保存副本。

     class MyTokenFieldCell: NSTokenFieldCell {
        static var cells = [NSUserInterfaceItemIdentifier: [MyTokenFieldCell]]()
    
        override func copy(with zone: NSZone? = nil) -> Any {
            let cell = super.copy(with: zone)
    
            guard let tokenFieldCell = cell as? MyTokenFieldCell else { return cell }
            tokenFieldCell.identifier = self.identifier
    
            guard let identifier = tokenFieldCell.identifier else { return cell }
            var cells = MyTokenFieldCell.cells[identifier] ?? []
            cells.append(tokenFieldCell)
            if cells.count > 4 {
                cells.removeFirst()
            }
            MyTokenFieldCell.cells[identifier] = cells
    
            return cell
        }
    }
    
  2. 实现tableView(_:dataCellFor:row:)的{​​{1}}方法,为table view提供NSTableViewDelegate,设置标识符为:MyTokenFieldCell

    <columnIdentifier>:<row>