ios - 在超类拥有的属性中应用属性包装器
问题描述
我已经为 UIView、UILabel 等 UI 组件的主题创建了自己的属性包装器。
class MyUIViewController: UIViewController {
@Theme private override var view: UIView! // it doesnt work!!!
@Theme private var myCustomView: UIView! // it works!!
}
在这种情况下,我会得到一个编译错误“不能用存储的属性'view'覆盖”
我知道视图是 UIViewController 的一个属性。您知道是否有任何可能的方法将属性包装器应用于存储的(超类)属性?任何建议将不胜感激:) 非常感谢!
解决方案
我找到了一种方法来做到这一点,但它更像是一种 hack而不是一个好的实现(所以我不推荐它),而且我还没有完全测试它(因为它真的在 UIViewController 视图加载机制上,这可能会导致一些未定义的行为)。
也就是说,在属性包装器文档中,您可以找到解释属性包装器如何工作的“翻译示例”。
@Lazy var foo = 1738
// translates to:
private var _foo: Lazy<Int> = Lazy<Int>(wrappedValue: 1738)
var foo: Int {
get { return _foo.wrappedValue }
set { _foo.wrappedValue = newValue }
}
所以我们可以模仿这个来手动包装一个超类属性。
请注意,在view
属性上执行此操作有点特殊,因为在视图控制器初始化期间未加载视图,但更像是一个惰性 var。
@propertyWrapper
struct Theme<WrappedValue: UIView> {
var wrappedValue: WrappedValue?
}
class Controller: UIViewController {
override func loadView() {
super.loadView()
_view.wrappedValue = view
}
private var _view: Theme<UIView> = .init()
override var view: UIView! {
get {
if _view.wrappedValue == nil {
// This is a trick I would not recommend using, but basically this line
// forces the UIViewController to load its view and trigger the
// loadView() method.
_ = super.view
}
return _view.wrappedValue
}
set {
_view.wrappedValue = newValue
}
}
}
我将属性包装器中的包装值设为可选,因为该view
属性nil
处于初始化过程中(因为尚未加载视图)
推荐阅读
- javascript - O(1) 二维坐标网格 JavaScript 的复杂度搜索数据结构
- php - 处理来自 cURL 请求的 JSON 响应的问题
- java - 是否有一种“正确”的方式将字符串和整数存储在 Java 中的同一个数组中?
- oauth - 使用 OAuth 2.0 登录的正确注销流程是什么
- r - glmnet 错误 (nulldev == 0) stop("y 是常数;高斯 glmnet 在标准化步骤失败")
- asp.net - 删除并重新添加后没有出现广告
- c# - 如何有效地将 EDMX 纳入解决方案
- javascript - 如果选中则禁用第二个选择框的选项
- javascript - 在Javascript中从数组中提取虚假值
- r - 在 R 中求解具有两个未知数的方程