swift NSTableHeaderCell子类具有委托属性的NSTableView崩溃

hof1towb  于 2023-03-11  发布在  Swift
关注(0)|答案(1)|浏览(138)

问题:

在NSTableHeaderCell子类中填充自定义委托属性时,代码将崩溃到App Delegate @Main。使用App Testing Address Sanitizer会显示此错误
NSTableView自定义标题单元格(17503,0x 11071 e600)内存分配:由于无法预先分配保留的VM空间,因此放弃了nano区域。

目标:

最终的结果是有一个简单的NSTableView,它有两列,我希望第1列标题中的控件有一个委托,当该控件中发生操作时,该委托将被调用。不是标题本身,而是添加到标题中的自定义控件(复选框)。

测试:

在这篇文章中,我删除了所有其他代码(复选框、覆盖等),并将其范围缩小到只有一个NSTableHeaderCell子类,该子类为委托提供了一个属性。
下面是带有函数的委托协议,以及带有保存委托的属性的CheckboxTableViewHeader子类

protocol CheckboxDelegate: AnyObject {
    func checkboxClicked() -> Void
}

class CheckboxTableViewHeader : NSTableHeaderCell {
    var myDelegate: CheckboxDelegate?
}

在视图控制器中唯一的代码是

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource, CheckboxDelegate {
.
.
.
override func viewDidLoad() {
    super.viewDidLoad()

    let firstCol = self.myTableView.tableColumns[0]
    self.myTableView.removeTableColumn(firstCol)

    let col0 = NSTableColumn(identifier: col0Id)
    col0.title = "col 0"
    let col1 = NSTableColumn(identifier: col1Id)
    col1.title = "col 1"
    self.myTableView.addTableColumn(col0)
    self.myTableView.addTableColumn(col1)

    let header = CheckboxTableViewHeader(textCell: "Col 1")

    header.myDelegate = self  // <-- this will cause a crash, but not here..
                              // ..crash occurs after viewDidLoad concludes

    self.myTableView.tableColumns[1].headerCell = header

    self.myTableView.dataSource = self
    self.myTableView.delegate = self
}

//
//MARK: - the custom header delegate
//
func checkboxClicked() {
    print(#function)
}

上面的代码删除了第一个表列(它在IB中有1个列),然后在代码中添加了第0列和第1列,然后尝试在子类中设置myDelegate变量。
上述代码header.myDelegate = self中指示的行将导致应用崩溃到AppDelegate中的@main。如果删除该行,它将正常工作。
请注意,我尝试向子类var test: Int添加另一种类型的var,如果在viewDidLoad header.test = 1中设置该属性而不是设置委托,它也可以正常工作,没有崩溃。

macOS: 12.6.3
XCode: 14.2
68bkxrlz

68bkxrlz1#

到目前为止,基于注解中引用的question and answer(这是一个不同的错误),添加此函数将覆盖

override func copy(with zone

看起来正在工作,代码不再崩溃到@main

class CheckboxTableViewHeader: NSTableHeaderCell {

    var buttonDelegate: CheckboxDelegate?

    override func copy(with zone: NSZone? = nil) -> Any {
        let copy = CheckboxTableViewHeader(textCell: self.stringValue)
        copy.buttonDelegate = buttonDelegate

        return copy
     }
}

请注意,错误仍显示在日志中
malloc:由于无法预先分配保留的虚拟机空间,因此放弃了nano区域。
这似乎不会影响应用程序,但如果你想摆脱这条消息,在XCode中,进入产品菜单-〉架构-〉编辑架构,然后在运行部分的参数选项卡中添加一个环境变量“MallocNanoZone”,并将其值设置为0

需要注意的是:这可能会影响应用程序在意想不到的方式,所以使用谨慎.

相关问题