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?
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.)