What does an app group look like on disk, and what happens with a group the target is not entitled to?
Predict first
What does containerURL return for the entitled group and for another group?
// entitlement: group.com.example.bank on App and Widget
let ok = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.bank")
let other = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.other")
- A Shared/AppGroup/<UUID> URL for the first; nil for the second
- nil for both
- A URL for both
Mental model. The group container is a shared mailbox in the lobby: both flats need a key, and the key must be for the same mailbox number.
In a built sample with the group group.com.example.bank on both the app and the widget, containerURL(forSecurityApplicationGroupIdentifier:) returned a folder under the simulator’s Containers/Shared/AppGroup/<UUID>, and xcrun simctl listapps showed it as the app’s GroupContainers entry. Asking for a different group (group.com.example.other) returned nil, the same symptom as a missing entitlement (Q402). UserDefaults(suiteName:) with the entitled group worked and read back 42. A group container is separate from the app’s own Containers/Data folder and it survives deleting the app only while another app of the same team still uses the group (device behaviour; not run).
Diagnostic order for “the widget sees nothing”: (1) is the group in both targets’ entitlements and spelled identically; (2) does containerURL return non-nil in the extension; (3) are both writing the same file path inside it; (4) is the data written atomically and read after the widget is reloaded (Q232). The simulator signs ad hoc with the entitlement file, which is enough for groups; a real device additionally needs the group registered in the developer account and a provisioning profile that includes it (not run).
Only entitled groups get a container; others return nil.
Common traps
- Force-unwrapping
containerURL. A typo in one target crashes the extension. - Assuming the group exists on a device because it worked in the simulator. The profile must contain it.
They might follow up with
- Where do I put shared files? In a subfolder of the group container, written atomically.
Related questions
- 19.1.2 How do app groups, shared containers and keychain access groups let an app and its extensions share data, and…
- 6.8.1 What is an app group, and what can go wrong when an app and an extension share a database?
- 6.8.3 Why is an app extension a separate process, and what does that mean for how you build it?
← What makes an extension valid inside an app bundle: the Info.plist… How do you make a shared payload that an older widget can still… →