4

For some reason, I need to serialize a class object that contains several closure fields.

Like this:

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

Is there any way I can get what I want?

shallowThought
  • 19,212
  • 9
  • 65
  • 112
Aofei Sheng
  • 121
  • 6
  • I think they are not archivable for the same reasons that Objective-C blocks aren't. The main reason being that archiving a closure would mean archiving any objects it captures (which would also have to be archivable), [this comment on another question](https://stackoverflow.com/questions/2172758/encoding-an-objective-c-block#comment30992816_2172845) talks about this. – paulvs Jun 25 '17 at 12:57

1 Answers1

5

Closures are not encodable or decodable as they are blocks code compiled into your program. Besides the fact that they might need to capture parts of the state of your program dynamically (which leads to a difficult technical challenge of making this work), consider the security implications of allowing you to arbitrarily encode and decode parts of the executable portions of your program: what happens when you attempt to reload the encoded class back into your app and run it? What if someone has maliciously edited an archive to insert code into your program? There is no reasonable way to tell whether the closure is valid/safe to run or not, past loading it back into your process.

This would be terribly insecure, and is generally not even allowed by the system. (Perhaps look into writable vs. executable memory — for this security reason, many operating systems designate blocks of memory as either being executable [e.g. the code in your program] or writable [e.g. data that you read into memory/manipulate], but not both.)

Itai Ferber
  • 28,308
  • 5
  • 77
  • 83