Eagerly Initializing Static Properties

In Xcode beta 5, since non objective-c classes cannot be marked @objc, a previous implementation of initialize() now won't be called when the class is initialized. Since static store properties are initalized lazily, is there a way to run an initialization function or to eagerly initialize a static property when the class loads?

You can just mark the static func initialize() as @objc instead of the whole class, and it looks like intialize() will still be called (including by subclasses of the class which implemented it, if they don't override) in an OS X playground in Xcode 7b5.


But use of intialize() should probably be considered unsafe from Swift. What are you trying to accomplish with it?

Run an initializaiton method one time before any clients call the static methods of the class.


Why is intialize() unsafe in swift?

To clarify, it is the Objective-C class load() method which gets called upon loading a class. This is the method that was unsafe in Swift and now is no longer allowed in Swift. I miss that capability because you could use it to perform runtime registration for example. The initialize() method only gets called before a class is used the first time. I haven't found a use case where I miss the initialize() class method.


What is your use case that you absolutely need something called that can't be done through lazy initialization? Maybe you have a special case. Typically, there is some resource you must be needing initialized, and you should be able to perform that initialization using lazy initialization.

I would consider using +initialize() unsafe because it is relying on an implementation detail of how Swift interacts with the objective-C runtime, and because it can be called multiple times by the objective-C runtime.


At the moment the Swift runtime is packaged with every app binary, but eventually it won't. It's possible that Swift classes won't have an @objc marked +initialize() called anymore in a future version of the runtime, and your code will start using the class without the intended initialization and will either silently keep going in an unexpected state and/or will cause a crash.


Also, the +initialize() call is already somewhat unsafe in objective-C, and some people spent a lot of time chasing very obscure bugs caused by the fact that their +initialize() code was being run multiple times in classes they assumed were final, because the objective-C runtime was dynamically generating subclasses to implement certain features.

Good points!


I have yet to encounter a use case that requires initialize(). I think the current Swift lazy static initialization is better than the initialize() method anyway. I'm curious to know if anyone has such a use case that cannot be addressed in pure Swift via lazy static initialization.

In Xcode 7.0.1, initialize is not being called in a swift subclass of NSObject when built in release mode.


There is no way on class load to run an initialization function in a swift singleton that has only static methods. The methods must be made instance methods and an instance accessor must be provided. It's not a problem, just a difference.

Lazy initialization implies non-concurrent access which will be another thorn in our side as Swift matures. There must be some form of planned, ordered execution that occurs in a predictable way so that we don't have to sprinkle lazy initialization around everywhere.

One of the primary problems I am confronting is in the use of SwiftData and making sure that there is at least one tuple in place for particular models that store and convey settings across the application.

The use of .modelContext() creates a lot of lazy initialization dependency problems because it doesn't really allow for the above initialization of at least one tuple to readily happen because of this:

Main actor-isolated property 'mainContext' can not be referenced from a non-isolated context

Eagerly Initializing Static Properties
 
 
Q