我试图让 SwiftData 存储 Core Graphics 基本结构,如 CGSize、CGRect、CGPoint,但它不起作用。我想 CGVector 和 CGAffineTransform 可以添加到列表中,但我还没有尝试过。
我的问题:制作 SwiftData 存储/检索 CG 结构的明智方法是什么?
这是我发现的: 所有 CG 结构通过符合 Encodable 和 Decodable 来符合 Codable。然而,它们都使用无密钥编码。未加密的编码将得到下面的简单类,从而导致崩溃
Fatal error: Composite Coder only supports Keyed Container
。
@Model
class TestCGSize {
// Fatal error: Composite Coder only supports Keyed Container
var cgSize: CGSize = CGSize.zero
init(cgSize: CGSize) { self.cgSize = cgSize }
}
旁注:致命错误消息并不完全正确,因为 CGFloat 可以工作并且 CGFloat 使用无密钥编码。
问题如何解决?
为 Codable 编写扩展: 无法使用新扩展覆盖 Encodable/Decodable 的现有实现。
编写子类:无法对结构进行子类化。
写一个@propertyWrapper:会产生编译错误:
Property wrapper cannot be applied to a computed property
。看来 SwiftData 将所有属性都变成了计算属性。
使用didSet观察者:它确实有效,但只是单向的。 SwiftData 将在数据库中创建列并存储值,但我只能部分检索。请参阅下面的测试代码。
编写一个包装器结构:从我的第一次尝试开始。任何可行的例子都将受到高度赞赏。
可能还有另一种我没有想到的方法。我将不胜感激任何帮助。
@Model
class TestCGSize {
@Transient
var cgSize: CGSize = CGSize.zero {
didSet {
cgSizeWidth = cgSize.width
cgSizeHeight = cgSize.height
}
}
// Columns created and data stored in db.
// Data retrieved, but cgSize not updated
var cgSizeWidth: Double = 0 {
didSet { cgSize.width = cgSizeWidth }
}
var cgSizeHeight: Double = 0 {
willSet { cgSize.height = newValue }
}
init(cgSizeWidth: Double, cgSizeHeight: Double) {
self.cgSizeWidth = cgSizeWidth
self.cgSizeHeight = cgSizeHeight
self.cgSize.width = cgSizeWidth
self.cgSize.height = cgSizeHeight
}
}
@Transient
创造了第二个真相来源。您可以通过将 cgSize
转换为具有 get
和 set
的计算属性来保持单一事实来源。
然后为了连续性,您可以设置数据库属性
private
。
import SwiftData
@Model
class TestCGSize {
var cgSize: CGSize {
get {
.init(width: _cgSizeWidth, height: _cgSizeHeight)
}
set {
self._cgSizeWidth = newValue.width
self._cgSizeHeight = newValue.height
}
}
// Columns created and data stored in db.
private var _cgSizeWidth: Double = 0.0
private var _cgSizeHeight: Double = 0.0
init(cgSize: CGSize) {
self.cgSize = cgSize
}
}