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

UIView的appearance()代理工作原理及自定义UIView的UIAppearance实现问题

问题原因
  • UIAppearance 是基于 Objective-C runtime 的消息转发机制实现的,只有暴露给 OC runtime 且开启动态分发的属性才能被 UIAppearance 识别调用。
  • 你当前定义的 TestView 以及它的 testColor 属性都是纯 Swift 实现,没有标记 OC 可见,也没有开启动态分发,当 UIAppearance 实例调用 testColor 的 setter 方法时就会触发方法未识别的崩溃。
修复方法

给自定义类和要支持外观配置的属性添加 @objc 和 dynamic 修饰即可:

// 给自定义类添加 @objc 标记,暴露给 OC 运行时
@objc final class TestView: UIView {
    // 给要支持 UIAppearance 的属性添加 @objc dynamic 修饰,开启 OC 动态分发
    @objc dynamic var testColor: UIColor = .white {
        didSet {
            backgroundColor = testColor
        }
    }
}

修改后原控制器代码无需改动,运行3秒后两个 TestView 都会自动变为红色,符合预期。

自定义 UIView 实现 UIAppearance 的通用规则
  • 所有要支持 UIAppearance 的属性必须添加 @objc dynamic 修饰符
  • Swift 定义的自定义 UIView 子类需要添加 @objc 标记,暴露给 OC 运行时
  • 支持 UIAppearance 的属性类型必须是可桥接到 OC 的类型:基础数值类型(CGFloat、Int 等)、UIKit 类、继承自 NSObject 的自定义类都可以,纯 Swift 类型(Struct、非桥接 Enum 等)不支持
  • 带参数的外观配置方法同样需要添加 @objc 修饰,示例:
@objc func setTestColor(_ color: UIColor, for state: UIControl.State) {
    // 内部逻辑实现
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 04:18:02