2017-06-25 12 views
3

何らかの理由で、いくつかのクロージャーフィールドを含むクラスオブジェクトをシリアル化する必要があります。このようクロージャをエンコードしてデコードする方法はありますか?

import Foundation 

class Foo: NSObject, NSCoding { 

    var bar: (() -> Void) 

    override init() { 
     bar = {} 
    } 

    required init(coder aDecoder: NSCoder) { 
     bar = aDecoder.decodeObject(forKey: "bar") as! (() -> Void) 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(bar, forKey: "bar") 
    } 

} 

let foo = Foo() 
foo.bar = { 
    print("Help!") 
} 

let data = NSKeyedArchiver.archivedData(withRootObject: foo) 
let object = NSKeyedUnarchiver.unarchiveObject(with: data) as! Foo 

は私が欲しいものを得ることができる方法はありますか?

+0

Objective-Cブロックがそうでないのと同じ理由でアーカイブ可能ではないと思います。主な理由は、クロージャをアーカイブすることは、キャプチャするオブジェクト(アーカイブ可能でなければならない)をアーカイブすることを意味します。[この別の質問に対するコメント](https://stackoverflow.com/questions/2172758/encoding-an-objective -c-block#comment30992816_2172845)これについて話します。 – paulvs

答えて

3

クローズは、プログラムにコンパイルされたブロックコードであるため、エンコードまたはデコードできません。プログラムの状態の一部を動的にキャプチャする必要があるかもしれないという事実のほかに(この作業を行うのは技術的な難題につながります)、実行可能な部分のコードを任意にエンコードしてデコードするセキュリティの影響を考慮してくださいプログラム:エンコードされたクラスをあなたのアプリケーションにリロードして実行しようとするとどうなりますか?誰かがあなたのプログラムにコードを挿入するために悪意を持ってアーカイブを編集した場合はどうなりますか?閉鎖が有効であるかどうかを判断する合理的な方法はありません。

これは非常に危険であり、一般にシステムによって許可されていないこともあります。 (おそらく、書き込み可能な対実行可能なメモリに見える - このセキュリティ上の理由のために、多くのオペレーティングシステムは、どちらかが実行可能であるとして、メモリのブロックを指定する[例えば、あなたのプログラムのコード]あなたがメモリに読み込ままたは書き込み可能[例えばデータ/操作]、両方ともではありません)。

関連する問題