You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:27:48