簡體   English   中英

核心數據中的安全編碼測量類,NSValueTransformers

[英]Secure Coding Measurement Classes in Core Data, NSValueTransformers

我有一個大量使用測量的應用程序。 它是用 SwiftUI/iOS 14 編寫的。我將數據保存在 Core Data 數據庫中。 該應用程序運行良好,直到我嘗試實施安全編碼。 我制作了一個示例應用程序來剝離除基礎之外的所有內容。 它基於 Xcode 的默認 Core Data 應用程序,幾乎沒有更改。 同樣,我可以很好地保存我的測量結果,直到我嘗試使用安全編碼。

xddatamodel以及錯誤如下: 在此處輸入圖像描述

我正在為實體使用手動代碼生成,它看起來像這樣:

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。

我使用了以下參考資料:

可轉換和 NSKeyedUnarchiveFromData

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM