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

Swift中结构体遵循带可选属性的@objc协议报错问题求助

问题原因

@objc修饰的协议属于类专属协议,仅允许Objective-C兼容的类(继承自NSObject的类)遵循,而结构体是值类型,无法适配这类协议,因此触发报错。


解决方案1:纯Swift协议扩展实现可选属性(推荐)

去掉@objc修饰符,通过协议扩展为isValid提供默认实现,这样结构体可正常遵循协议,且无需强制实现该属性:

protocol MyProtocol {
    var id: UUID { get set }
}

// 给协议添加可选属性的默认实现
extension MyProtocol {
    var isValid: Bool {
        // 默认逻辑,可根据需求调整
        return false
    }
}

// LastKey保留自定义isValid实现,会覆盖默认逻辑
struct LastKey: Equatable, MyProtocol {
    var id: UUID
    let lowercase: String?

    var isValid: Bool {
        // 自定义校验逻辑示例
        return lowercase?.isEmpty == false
    }
}

// FirstKey无需实现isValid,自动使用默认实现
struct FirstKey: Equatable, MyProtocol {
    var id: UUID
    let name: String?
}

之后在函数中可直接访问isValid:

func setLastKey(_ lastKey: MyProtocol) {
    if lastKey.isValid {
        // 执行业务逻辑
    }
}

解决方案2:将结构体改为类(仅当业务允许时使用)

如果业务逻辑可以接受用类替代结构体,可保留@objc协议,同时将类型改为继承自NSObject的类:

@objc protocol MyProtocol {
    var id: UUID { get set }
    @objc optional var isValid: Bool { get set }
}

class LastKey: NSObject, Equatable, MyProtocol {
    var id: UUID
    let lowercase: String?

    var isValid: Bool {
        // 自定义校验逻辑示例
        return lowercase?.isEmpty == false
    }

    init(id: UUID = UUID(), lowercase: String?) {
        self.id = id
        self.lowercase = lowercase
    }

    static func == (lhs: LastKey, rhs: LastKey) -> Bool {
        return lhs.id == rhs.id && lhs.lowercase == rhs.lowercase
    }
}

class FirstKey: NSObject, Equatable, MyProtocol {
    var id: UUID
    let name: String?

    init(id: UUID = UUID(), name: String?) {
        self.id = id
        self.name = name
    }

    static func == (lhs: FirstKey, rhs: FirstKey) -> Bool {
        return lhs.id == rhs.id && lhs.name == rhs.name
    }
}

注意:类必须继承NSObject才能遵循@objc协议,且需手动实现Equatable的==方法。


内容的提问来源于stack exchange,提问作者Duck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:54:51