Here's how to set and read UserDefaults
between two apps:
- Select your project in the project navigator
- Select the main app target and go to the capabilities tab
- Turn on "App groups"
- Create a new container that starts with “group.”, so give it a name like “group.foo.bar”.
- Select your Keyboard Extension target and switch on app groups again. Don’t create a new container, rather select the created container (group.foo.bar) to signify that the Keyboard Extension is a member of the container.
This is how you write to the UserDefaults
:
let defaults = UserDefaults(suiteName: "group.foo.bar") //replace suiteName with your container name
let defaultValue = ["userUID" : ""]
defaults!.register(defaults: defaultValue)
defaults!.set("a", forKey: "userUID")
defaults!.synchronize()
And how to read from the keyboard extension:
let defaultsToKeyboard = UserDefaults(suiteName: "group.foo.bar") //replace suiteName with your container name
let uid = defaultsToKeyboard?.object(forKey: "userUID")
print("\(uid)")
Basically this allows apps that is part of the group to access the same UserDefaults
. UserDefaults
are not destroyed even after the containing app is deleted. UserDefaults
are always saved to disk, so it will never be destroyed. When you use app sharing, your apps inside the group are actually accessing the same UserDefaults
. That's why there is a synchronize
function, it saves the UserDefaults
to disk and also why it is unsafe, anybody who can see the underlying file system can look at its contents.
Your extension can also 'see' the UserDefaults
. It just can't access it. Creating group ids tells iOS that your extension (or even app) is authorized to access it, so it can read and write data to and from it.
Your app is not needed to be in the foreground to access the UserDefaults
as it is saved on disk already!
Remember that UserDefaults
are saved to disk and not stored in an instance!