![](/img/trans.png)
[英]Saving a UIImage into core data; trouble with NSValueTransformers
[英]Secure Coding Measurement Classes in Core Data, NSValueTransformers
我有一個大量使用測量的應用程序。 它是用 SwiftUI/iOS 14 編寫的。我將數據保存在 Core Data 數據庫中。 該應用程序運行良好,直到我嘗試實施安全編碼。 我制作了一個示例應用程序來剝離除基礎之外的所有內容。 它基於 Xcode 的默認 Core Data 應用程序,幾乎沒有更改。 同樣,我可以很好地保存我的測量結果,直到我嘗試使用安全編碼。
我正在為實體使用手動代碼生成,它看起來像這樣:
extension Item {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
return NSFetchRequest<Item>(entityName: "Item")
}
@NSManaged public var timestamp_: Date?
@NSManaged private var notes_: String?
@NSManaged private var length_: Measurement<UnitLength>?
public var timestamp: Date {
get { timestamp_ ?? Date(timeIntervalSince1970: 0) }
set { timestamp_ = newValue }
}
public var notes: String {
get { notes_ ?? "Add Notes Here..." }
set { notes_ = newValue }
}
public var length: Measurement<UnitLength> {
get { length_ ?? Measurement(value: 0, unit: UnitLength.meters) }
set { length_ = newValue }
}
}
雖然我嘗試在不同的地方注冊 ValueTransformer,但我目前在 @main 中有它:
@main
struct Core_Data_TestApp: App {
let persistenceController: PersistenceController
init() {
UnitLengthValueTransformer.register()
persistenceController = PersistenceController.shared
}
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
我的 ValueTransformer 看起來像這樣:
@objc(UnitLengthValueTransformer)
final class UnitLengthValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: UnitLengthValueTransformer.self))
override static var allowedTopLevelClasses: [AnyClass] {
return [UnitLength.self]
}
public static func register() {
let transformer = UnitLengthValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
}
據我所知,存在分歧,UnitLength 的 class header 是:
open class UnitLength : Dimension, NSSecureCoding
所以它確實符合 NSSecureCoding。
我使用了以下參考資料:
iOS 13+ 中的 CoreData 可轉換和 NSSecureCoding
Core Data 中的 ValueTransformer 解釋:存儲絕對 URL
我仍然得到同樣的錯誤:
Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred.", [:]: file Core_Data_Test/ContentView.swift, line 57
我無法弄清楚我做錯了什么導致崩潰。
感謝@LeoDabus,我終於能夠敲定這一點。 關鍵是將 Swift Measurements 轉換為 NSMeasurement 並在 Core Data 中使用 NSMeasurement。 您需要將自定義 class 設置為NSMeasurement
。 您的轉換器將是一個自定義值轉換器。 我打電話給我NSMeasurementValueTransformer
。 您的.xcdatamodeld 將如下所示:
@objc(NSMeasurementValueTransformer)
final class NSMeasurementValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: NSMeasurementValueTransformer.self))
override static var allowedTopLevelClasses: [AnyClass] {
return [NSMeasurement.self]
}
public static func register() {
let transformer = NSMeasurementValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
}
有趣的是,我不必注冊值轉換器。 也許有人可以解釋原因,但無需注冊即可使用。
最后,在一個擴展中,我聲明了一個面向公眾的變量,它處理變量從我想使用的測量值轉換到我想使用的測量值,如下所示:
extension Item {
public var length: Measurement<UnitLength> {
// The getter returns an actual value, not an optional. If you want to return an optional, just use:
// get { length_ as Measurement<UnitLength> }
get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
set { length_ = newValue as NSMeasurement }
}
}
你會注意到核心數據屬性被命名為length_
。 我仍然可以在我的應用程序中使用 Swift 測量,但將它們安全地存儲在核心數據中。 這修復了核心數據警告:
CoreData:此應用程序中的一個或多個模型正在使用帶有未設置或設置為 NSKeyedUnarchiveFromDataTransformerName 的轉換器名稱的可轉換屬性。 請改用“NSSecureUnarchiveFromData”或 NSSecureUnarchiveFromDataTransformer 的子類。 在某些時候,當指定 nil 時,Core Data 將默認使用“NSSecureUnarchiveFromData”,並且包含不支持 NSSecureCoding 的類的可轉換屬性將變得不可讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.