提问人:Michael May 提问时间:11/16/2023 更新时间:11/17/2023 访问量:80
UIColor 可以持久化在 SwiftData 中吗
Can UIColor be persisted in SwiftData
问:
我正在尝试通过 SwiftData 持久化一个包含该类型属性的数据模型。我按照 [教程][1] 使用声明并实现了 .完整的代码如下。UIColor
@Attribute(.transformable(by: UIColorValueTransformer.self)) var tileColor: UIColor?
UIColorValueTransformer' which subclasses 'ValueTransformer
但是,Xcode 会引发运行时异常,并显示错误消息“SwiftData/SchemaCoreData.swift:244:致命错误:无法初始化 UIColorValueTransformer”。我不知道复杂的模型如何通过 SwiftData 持久化或持久化。ValueTransformer
UIColor
Color
// Tile.swift
import SwiftData
import UIKit
@Model
final class Tile {
@Attribute (.unique) var name: String
var type: String
var @Attribute(.transformable(by: UIColorValueTransformer.self)) var tileColor: UIColor?
init(name: String, type: String, tileColor: UIColor) {
self.name = name
self.type = type
self.tileColor = tileColor
}
}
final class UIColorValueTransformer: ValueTransformer {
override class func transformedValueClass() -> AnyClass {
return UIColor.self
}
// return data
override func transformedValue(_ value: Any?) -> Any? {
guard let color = value as? UIColor else { return nil }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: true)
return data
} catch {
return nil
}
}
// return UIColor
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else { return nil }
do {
let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data)
return color
} catch {
return nil
}
}
}
// TileApp.swift
import SwiftUI
import SwiftData
@main
struct TileApp: App {
init() {
ValueTransformer.setValueTransformer(UIColorValueTransformer(), forName: NSValueTransformerName("UIColorValueTransformer"))
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: [Tile.self])
}
}
}
非常感谢您的帮助。 [1]:https://azamsharp.com/2023/07/04/the-ultimate-swift-data-guide.html
答:
0赞
Michael May
11/17/2023
#1
如上@Bram所示,解决方案如下:
// Tile.swift
import SwiftData
import UIKit
@Model
final class Tile {
@Attribute (.unique) var name: String
var type: String
var @Attribute(.transformable(by: UIColorValueTransformer.self)) var tileColor: UIColor?
init(name: String, type: String, tileColor: UIColor) {
self.name = name
self.type = type
self.tileColor = tileColor
}
}
@objc(UIColorValueTransformer) // The solution is adding this line
final class UIColorValueTransformer: ValueTransformer {
override class func transformedValueClass() -> AnyClass {
return UIColor.self
}
// return data
override func transformedValue(_ value: Any?) -> Any? {
guard let color = value as? UIColor else { return nil }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: true)
return data
} catch {
return nil
}
}
// return UIColor
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else { return nil }
do {
let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data)
return color
} catch {
return nil
}
}
}
// TileApp.swift
import SwiftUI
import SwiftData
@main
struct TileApp: App {
init() {
ValueTransformer.setValueTransformer(UIColorValueTransformer(), forName: NSValueTransformerName("UIColorValueTransformer"))
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: [Tile.self])
}
}
}
评论