and the presenter states about (third-party) frameworks :
“... and these initializers are always run whenever the framework is linked, or the class is loaded.”
I know about +load and +initialize in Objective-C code, but as far as I remember, the possibility to use initialize() in Swift for a one-time initialization has been removed some time ago. Indeed, this does not compile in Xcode 10:
import Foundation
class MyClass: NSObject {
override static func initialize() { }
// Method 'initialize()' defines Objective-C class method 'initialize', which is not permitted by Swift
}
So what am I missing here? What Swift initialize() method is the talk referring to?
Just a mistake in the talk, I think! Swift doesn't currently have any supported way to do load-time initialization, or implicit-on-first-use-of-class initialization. The recommended pattern is to use a static variable for one-time, thread-safe initialization on first use. We'd also like to collect cases where people do need something more than that; one of them that we know about is registering subclasses of a particular class for some kind of lookup later. Please file a bug if you have another one in mind.
I've been looking for something like this for a while; something like __attribute__((constructor)) would be really useful once Swift has ABI stability (and even today, for some projects, where I can guarantee that my plugin is the only one using Swift, or that everything was compiled together) because it'd allow plugins and bundles to run code when they're loaded. Static variables aren't good enough because in this context there's no way to get code execution otherwise.
We do need a better way to do registration; the best way right now is to have some known class name and do something like NSClassFromString("\(pluginName).Manager"). What else do you want code-execution-on-load for? (instead of on-first-use)
One kind of ugly but surprisingly common case is to replace implementations or add functionality in a binary that knows nothing about you, or has a limited API that is not enough for what you need. Your plugin is loaded in some way, often through NSPlugin which expects to call your NSPrincipalClass's initialize method to perform all your work (and has no other formal API), but sometimes through DYLD_INSERT_LIBRARIES or similar where __attribute__((contructor)) is the only way to get the plugin to do anything. From there you might swizzle something so that your custom implementation is called for whatever you need: custom instrumentation, swapping out the behavior of a particular subsystem, etc.