Swift与Objective-C共用Bool类型的最优实现方案咨询
最优解决方案
首先纠正一个误区:NSNumber是完全支持Codable协议的,直接将属性声明为@objc var property: NSNumber?是可以正常完成编码解码的。但如果希望Swift代码中依然使用更符合语言习惯的Bool?类型,同时兼容Objective-C访问,最优雅的方式是通过双向同步的双属性实现:
class Test: NSObject, Codable { // Swift侧专用的Bool?属性,负责Codable编解码 var swiftProperty: Bool? { didSet { objcProperty = swiftProperty.map(NSNumber.init(value:)) } } // Objective-C侧可见的NSNumber?属性,用@objc暴露 @objc var objcProperty: NSNumber? { didSet { swiftProperty = objcProperty?.boolValue } } // 自定义Codable的编码解码逻辑,仅处理Swift侧属性 enum CodingKeys: String, CodingKey { case swiftProperty } override init() { super.init() } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) swiftProperty = try container.decodeIfPresent(Bool.self, forKey: .swiftProperty) objcProperty = swiftProperty.map(NSNumber.init(value:)) try super.init() } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(swiftProperty, forKey: .swiftProperty) } }
方案细节
- Swift代码中直接使用
swiftProperty(Bool?类型),符合Swift的类型安全习惯,所有编解码逻辑都围绕这个属性展开,避免类型转换的麻烦。 - Objective-C代码中通过
objcProperty(NSNumber*类型)访问,完全兼容ObjC的类型系统,不需要额外转换。 - 两个属性通过
didSet实现双向自动同步,确保两边的值始终保持一致,不会出现数据不一致的问题。 - 自定义
Codable方法明确指定编解码的键,避免自动合成的逻辑影响属性同步。
如果你的业务场景可以接受属性非可选(即有默认值),还可以用更简洁的写法:利用Swift到Objective-C的自动桥接,将非可选Bool标记为@objc,这样两边都能直接使用:
class Test: NSObject, Codable { @objc var property: Bool = false }
这种方式下,Swift侧用Bool类型,Objective-C侧会自动桥接为BOOL类型,同时Codable的自动合成逻辑也能正常工作,适合不需要nil值的场景。
内容的提问来源于stack exchange,提问作者Begbie
相关产品推荐
相关产品推荐

