NSTableView中的NSTokenFieldCell在tab时崩溃,这是一个bug吗?



我在使用NSTokenFieldCell时遇到了麻烦,所以我继续在Xcode中创建一个新项目来隔离问题。以下是我所做的:

  • 将一个NSTableView放到主窗口;
  • 选择第二列的文本单元格,并改变它的类(通过身份检查器)为NSTokenFieldCell;
  • 实现了一个最小的数据源对象,代码如下:

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

起初它似乎工作得很好,但如果您双击一个单元格进行编辑,然后tab和shift+tab来回切换单元格,最终当令牌字段单元格接收焦点时,应用程序会因坏访问而崩溃。

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

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

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(仅用于令牌列),但我得到了相同的错误。

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

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

所以我反复尝试找到一个更好的解决方案:

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

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

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


以下是原答案

⚠️由于解决方案会引起其他问题,请忽略

我也遇到过这个问题。我的解决方案是暂时保留表格视图使用的单元格。

  1. Custom 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. 实现NSTableViewDelegatetableView(_:dataCellFor:row:)方法,为表视图提供MyTokenFieldCell,并设置标识符为:<columnIdentifier>:<row>

    extension ViewController: NSTableViewDelegate {
        func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell? {
            guard let columnIdentifier = tableColumn?.identifier, columnIdentifier.rawValue == "token" else {
                return tableColumn?.dataCell(forRow: row) as? NSCell
            }
            let cell = MyTokenFieldCell()
            cell.isEditable = true
            cell.identifier = .init("(columnIdentifier.rawValue):(row)")
            return cell
        }
    }
    

相关内容

  • 没有找到相关文章

最新更新