提问人:Alex Sh. 提问时间:9/22/2023 最后编辑:Alex Sh. 更新时间:9/25/2023 访问量:39
获取 Swift ReferenceWritableKeyPath 的字符串表示形式失败(返回指针而不是类型)
Getting String representation of Swift ReferenceWritableKeyPath is failed (returns pointer instead of type)
问:
我有一个继承自 Realm 的类:Product
Object
@objc class Product: Object {
@Persisted(primaryKey: true) var id: String = ""
@Persisted var externalId: String?
@Persisted var name: String?
}
我尝试编写一个用于对象更新的通用方法,该方法采用带有 keyPaths 和值的字典,并使用以下 Realm 方法更新对象:
func setValue(_ value: Any?, forKey key: String)
这是一个计算变量,用于获取 KeyPath 的 String 表示形式:
fileprivate extension KeyPath {
var asString: String {
let wholeString = String(describing: self)
let dropLeading = "\\" + String(describing: Root.self) + "."
let keyPathString = "\(wholeString.dropFirst(dropLeading.count))"
return keyPathString
}
}
它在调试模式下可以完美运行,但是当我使用 Release 方案而不是它构建应用程序时,它会返回类似的东西,并且应用程序在尝试为此键路径设置值时崩溃。"Product.name"
"\Product.<computed 0x000000010c51ed18 (Bool)>
如果有人知道如何解决这个问题,将不胜感激。
更新:这个想法是将 Realm 的使用封装在类中。这是更新 Realm 实体的原始方法:
func updateObjects<DBEntity: Object, KeyPathType: NSObject, T>(
ofType objectType: DBEntity.Type,
where query: ((Query<DBEntity>) -> Query<Bool>)? = nil,
with keyedValues: [KeyPath<KeyPathType, T>: T],
completion: (Error?) -> Void?
)
使用 KeyPath 而不是简单的 String 的主要动机是最大程度地减少错误并防止因属性名称更改而导致的崩溃。因此,使用 for 参数不是一种选择。[String : T]
keyedValues
目前,似乎不能保证 Swift KeyPath 被转换为人类可读的字符串,因此该选项也不可用。
我最终修改了我的更新方法,如下所示:
func updateObjects<DBEntity: Object>(
ofType objectType: DBEntity.Type,
where query: ((Query<DBEntity>) -> Query<Bool>)? = nil,
updateBlock: @escaping ([DBEntity]) -> Void,
completion: DBOperationCompletion?
)
现在,我更新了 .updateBlock
答: 暂无答案
评论
String(describing:)
并且绝对不是这项工作的正确工具。如您所见,编译器在不需要属性名称的情况下会优化属性名称。哎呀,它甚至可以完全优化属性的存在(即,具有常量值的存储属性可以内联,许多存储的属性可以内联,就好像它们是任何其他函数一样)。 没有提供用于获取字符串名称的 API,这是有意为之的,因为这将是所有这些优化的巨大障碍。String(reflecting:)
KeyPath
String
someProduct.name = "soap"
let p = Product(value: ["id": "1", "name": "soap"])