web-dev-qa-db-ja.com

Core Data&Xcode 11:「NSSecureUnarchiveFromData」またはNSSecureUnarchiveFromDataTransformerのサブクラスを使用するように切り替えてください

Xcode 11に移動し、起動時に次のクラッシュが発生しました:

CoreData:障害:このアプリケーションの1つ以上のモデルが、未設定またはNSKeyedUnarchiveFromDataTransformerNameに設定されているトランスフォーマー名を持つ変換可能なプロパティを使用しています。代わりに「NSSecureUnarchiveFromData」またはNSSecureUnarchiveFromDataTransformerのサブクラスを使用するように切り替えてください。 nilを指定すると、ある時点でCore Dataはデフォルトで「NSSecureUnarchiveFromData」を使用するようになり、NSSecureCodingをサポートしないクラスを含む変換可能なプロパティが読み取れなくなります。

CoreData:警告:エンティティ 'Group'のプロパティ 'color'はnilまたは安全でないNSValueTransformerを使用しています。代わりに「NSSecureUnarchiveFromData」またはNSSecureUnarchiveFromDataTransformerのサブクラスを使用するように切り替えてください。

以下のコードを使用して、起動時にNSPersistentContainerを作成しています。

private let container: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())
    let storeDescription = NSPersistentStoreDescription(url: getStoreURLWithUserName())
    storeDescription.shouldMigrateStoreAutomatically = true
    storeDescription.shouldInferMappingModelAutomatically = true
    container.persistentStoreDescriptions = [storeDescription]
    return container
}()

この行が実行された直後にエラーが発生します:

let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())

また、変換可能な 'Colorin aGroup`エンティティと呼ばれるプロパティがあります。

@NSManaged public var color: UIColor?
@NSManaged public var hexColorValue: String?

以下は、プロパティの設定方法です。

public var hexColor: String? {
    get {
        return self.hexColorValue
    }
    set {
        self.hexColorValue = newValue
        if let str = newValue {
            self.color = UIColor(hex: str)
        }
    }
}

これは、コアデータでのプロパティの外観です。

enter image description here

このクラッシュから回復する方法がわかりません。これはXcode 10で正常に動作していました

9
user1107173

Xcode 11に更新するときに同じ警告メッセージが表示されましたが、私の場合は警告であり、クラッシュはありません。

最良の解決策を見つけるために、変換可能な属性を含む単一のエンティティーのみを含む、簡略化されたサンプルアプリを作成してみました。しかし、何を試しても問題を再現できなかったようです。モデルファイルをメインアプリからデモアプリにコピーしましたが、もちろん失敗しました。

それで、2つのモデルファイルと、モデルを開いて永続ストアコンテナーを作成する以外に何もしない単純な単体テストができるようになりました。

 func testDataModels() {
     openDataModel(named: "samplemodel")
     openDataModel(named: "appmodel")
 }

 func openDataModel(named name: String) {
    print("Opening \(name)")
     guard let url = findFile(forResource: name, withExtension: "momd"),
           let managedObjectModel = NSManagedObjectModel(contentsOf: url)
     else {
         XCTFail("Unable to find \(name) data model")
         return
     }
    print(url)
     _ = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
 }

 func findFile(forResource name: String, withExtension ext: String) -> URL? {
     if let url = Bundle(for: type(of: self)).url(forResource: name, withExtension: ext) {
         return url
     }
     return Bundle.main.url(forResource: name, withExtension: ext)
 }

Appmodelはエラーメッセージを引き起こしますが、サンプルモデルはそうではありません。 appmodelを1つのエンティティに取り除いても、エラーが発生し続けます。

Samplemodelの内容をappmodel(Finderにパッケージの内容を表示)と比較すると、samplemodelには.xccurrentversionという名前の隠しファイルがありますが、appmodelにはありません。ファイルは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.Apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>_XCCurrentVersionName</key>
    <string>samplemodel.xcdatamodel</string>
</dict>
</plist>

そこで、appmodel用に同様のファイルを作成し、パッケージフォルダーに配置しました。驚いたことに、それは警告メッセージを沈黙させます!逆に、samplemodelから.xccurrentversionファイルを削除すると、エラーメッセージが生成されます。これにより、問題を個別にテストできます。

したがって、これは短期的な修正かもしれません。その間、私は安全なコーディングに移行する方法を考え出す必要があります。

1
Dale

TransformerプロパティをNSSecureUnarchiveFromDataTransformerに設定すると、私の場合の警告が解決されました。このために属性を選択し、そのトランスフォーマータイプをNSSecureUnarchiveFromDataTransformerに設定し、commond + Rを押して再度実行します。

ありがとう、Ratneshwar

1

変換可能な属性については、[カスタムクラス]フィールドでそのタイプを設定する必要があります。

たとえば、数値の配列を格納する変換可能なフィールドがあり、そのカスタムクラスは[Int16]として宣言されています。これはおそらくクラッシュの原因です。また、@ vadianが前述したように、両方のフィールドは必要ありません。

クラッシュが修正されたら、TransformerフィールドをNSSecureUnarchiveFromDataに設定することで警告を取り除くことができます(これをフィールドに入力するだけです)

0
Angel Olvera