14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Core Dataのtransformableな属性をセキュアに実装する

Last updated at Posted at 2020-09-12

Core Dataのエンティティが持つ属性 (attribute) の型は整数、文字列、日付などいくつかの決まったものしかとることができませんが、Transformableを指定することで任意の型を NSData に変換して保存することができるようになっています。このとき保存したい型と NSData の変換を担うのがvalue transformerです。

Core Dataのtransformableを利用しているプロジェクトをXcode 12でビルドしたときに、以下のような警告が出るようになりました。

warning: Misconfigured Property: <NSManagedObjectのサブクラス>.<プロパティ> is using a nil or insecure value transformer. Please switch to NSSecureUnarchiveFromDataTransformerName or a custom NSValueTransformer subclass of NSSecureUnarchiveFromDataTransformer

これは、これまでのvalue transformerが NSCoding を使ったものであるため非推奨になっており、 NSSecureCoding をベースとした NSSecureUnarchiveFromDataTransformer に置き換える必要があるということです。

今回この警告の対応のために調べた、 NSSecureUnarchiveFromDataTransformer を使ってtransformableな属性をセキュアに実装する方法をまとめました。

カスタムクラスが不要なパターン

NSSecureUnarchiveFromDataTransformer が扱える型は allowedTopLevelClasses で規定されていて、以下の通りです。

NSArray, NSDictionary, NSSet, NSString, NSNumber, NSDate, NSData, NSURL, NSUUID, NSNull

これらの型の組み合わせで表現できるもの、例えば文字列の配列 [String] の属性であれば、モデルエディタでTransformerの欄に NSSecureUnarchiveFromDataTransformerName を指定するだけでOKです。

カスタムクラスが必要なパターン

上に挙げた型以外の NSSecureCoding に準拠した標準の型(UIColor など)や、NSSecureCoding に準拠した独自の型を使う場合は、 NSSecureUnarchiveFromDataTransformer を継承したカスタムクラスを実装する必要があります。

// Core Dataで利用するために @objc が必要です
@objc final class SecureValueTransformer: NSSecureUnarchiveFromDataTransformer {

    // クラス名をvalue transformerのnameとします
    static let name = NSValueTransformerName(rawValue: String(describing: SecureValueTransformer.self))

    // superが返すクラスの配列に追加する形で使用するクラスを指定します
    override static var allowedTopLevelClasses: [AnyClass] {
        super.allowedTopLevelClasses + [
            UIColor.self,
            NSTimeZone.self,
            CustomTypeA.self,
            CustomTypeB.self,
        ]
    }

    // value transformerを登録する処理です。Core Data Stackの初期化前に呼びます。
    public static func register() {
        let transformer = SecureValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }

}

モデルエディタではTransformerの欄に name で指定したクラス名を入力します。

最後にCore Data Stackの初期化前に以下を実行して、value transformerを登録します。

SecureValueTransformer.register()

参考リンク

14
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?