如何编程移除NSBinding中NSBindingOption配置的值转换器
问题场景
开发 macOS 应用时,通过编程方式给 NSTextField 绑定了自定义 NSValueTransformer,初始绑定代码如下:
@IBOutlet var plcAddrLabel: NSTextField! @objc dynamic var registerAddr = Int(1) var optionsDict: [NSBindingOption : Any] = [:] optionsDict = [ NSBindingOption.valueTransformer: decToHexTransformer(), NSBindingOption.valueTransformerName: NSValueTransformerName.decToHexTransformerName ] plcAddrLabel.bind(.value, to: self, withKeyPath: "plcRegisterAddress" , options: optionsDict)
需要移除该绑定配置的值转换器,测试多种方案均触发报错。
已尝试的错误方案与报错
传入字符串"
"重绑定清除转换器,代码如下: optionsDict = [ NSBindingOption.valueTransformer: "<null>", NSBindingOption.valueTransformerName: "<null>" ] plcAddrLabel.bind(.value, to: self, withKeyPath: "plcRegisterAddress" , options: optionsDict)运行时触发崩溃,报错信息:
-[NSTaggedPointerString transformedValue:]: unrecognized selector sent to instance 0x7b73031cc07cbe65
该方案的思路来源:首次绑定NSValueTransformer之前,调用
plcAddrLabel.infoForBinding(.value)返回的结果中,NSValueTransformer与NSValueTransformerName字段的值均显示为""。 传入
NSBindingOption.nullPlaceholder作为配置值:optionsDict = [ NSBindingOption.valueTransformer: NSBindingOption.nullPlaceholder, NSBindingOption.valueTransformerName: NSBindingOption.nullPlaceholder ]仍然触发和上面一致的unrecognized selector报错。
补充现象
plcAddrLabel.infoForBinding(.value)返回结果中NSNullPlaceholder字段的值同样显示为"" - 只要尝试移除/清除转换器选项,就会触发转换器调用
- 值转换器正常绑定到NSTextField时运行完全正常,将当前绑定的转换器替换为另一个转换器也可正常生效
- 开发环境:Xcode 13.2.1
问题原因
infoForBinding返回结果中显示的"NSNull单例对象的日志输出,不是字符串<null>,也不是NSBindingOption相关枚举值。传入字符串、枚举值这类非NSValueTransformer类型的对象时,系统会默认将传入对象当做转换器实例,调用transformedValue:方法,自然触发找不到方法的崩溃。
可行解决方案
方案1:先完全解绑再重新绑定(最稳定推荐)
调用Cocoa绑定自带的unbind方法移除原有绑定,再重新发起不带转换器配置的绑定即可,示例代码:// 移除现有value绑定 plcAddrLabel.unbind(.value) // 重新绑定,不传入任何转换器相关配置 plcAddrLabel.bind(.value, to: self, withKeyPath: "plcRegisterAddress", options: nil)方案2:重绑定时传入真正的NSNull空值
如果不想完全解绑重建绑定,重绑定配置时传入NSNull.null单例对应转换器配置项即可,不要传字符串,示例代码:let resetOptions: [NSBindingOption: Any] = [ .valueTransformer: NSNull.null, .valueTransformerName: NSNull.null ] plcAddrLabel.bind(.value, to: self, withKeyPath: "plcRegisterAddress", options: resetOptions)
注意:Cocoa的绑定配置集合中不能存储nil值,所有空值都是用NSNull.null单例表示,不要把日志打印的<null>文本当做实际配置值传入。
内容的提问来源于stack exchange,提问作者helioz

