Binding to Shared User Defaults might fail in Xcode storyboards

While binding to the Shared User Defaults in .xib files is very easy I had hard times to achieve application wide preferences in projects based on storyboards. The behavior is a bit strange/unexpected and even in Xcode 15.4 it seams not to be completely solved. Issue is that IB only creates a single instance of a Shared User Default controller for the first scene, where it was requested and linking to this instance from other scenes offers no functionality. Even worse IB suggests this as first binding proposal. Here an example to deal with this issue.

  • add slider and label to view of ViewController in IB storyboard
  • add MenuItem to windows menu in the Application Scene When running the app this menu item remains disabled as no action is connected
  • bind value of the created menu item to the Shared User Defaults with Model Key Path: “showTerminal“ This creates a Shared User Defaults Controller instance that we use later. Now running the app the menu item is enabled and the checkmark toggles each time
  • add a checkbox to the view
  • add a User Default Controller to the View Controller Scene This must be repeated for any further Window- or View- Controller scene where a binding to the user defaults is required.
  • bind the checkbox to the newly added User Defaults Controller (but not the Shared User Defaults Controller) keeping the suggested Controller key values and set the Model Key Path to “showTerminal“ as above

now bind the slider and the label to the same User Defaults controller using an identical Model key If accidentally bound to the Shared User Defaults Controller (this is what IB suggests) no functional binding will take place!

  • Register the defaults early (before the nib is being loaded) to set default values like for example:
class AppDelegate: NSObject, NSApplicationDelegate {

	override init() {
		super.init()
		UserDefaults.standard.register(defaults: 
			[  "first": 0.0
			 , "showTerminal": false
			]
		)
	}
…
} 

[https://github.com/MissingManual/UserDefaultsBindingsInStoryboard]

ATTENTION: Suggestion is, to create the first Defaults Controller as a Shared User Defaults Controller inside the Application scene. Somehow Xcode remembers settings of the Shared User Default Controller and otherwise bindings might fail.

MESSAGE: Never bind to the “Shared User Default Controller“ but to individually created “User Default Controller“ for every scene, unless it is the very first time.

Alternatively you can set a let variable as

@objc let defaults = UserDefaults.standard

for example in each ViewController and then bind to this by

  • Bind to: ViewController
  • Controller Key:
  • Model Key Path: defaults.<your bindingname>
Binding to Shared User Defaults might fail in Xcode storyboards
 
 
Q