Call Directory Extension中UserDefaults来电识别启用失败问题
Let's dive into solving your issue step by step:
Root Cause
That error log you're seeing is the critical hint:
[User Defaults] Couldn't read values in CFPrefsPlistSource<0x10fe251d0> (Domain: GROUP_NAME, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd
Even though your print statements show you can read data from UserDefaults, Call Directory Extensions operate under strict sandbox constraints during the enablement process. The standard UserDefaults(suiteName:) initializer uses kCFPreferencesAnyUser under the hood, which isn't permitted for non-system extensions. The system blocks enablement even if debug reads work, because this access pattern violates sandbox rules.
Solution: Switch to CFPreferences API
Replace your UserDefaults usage with the lower-level CFPreferences APIs, which let you explicitly target the current user (allowed for your app group container). Update your retrieval function like this:
private func retrievePhoneNumbersToIdentifyAndLabels() -> (phoneNumbers: [CXCallDirectoryPhoneNumber], labels: [String]) { let appGroupID = GROUP_NAME as CFString let currentUser = kCFPreferencesCurrentUser let currentHost = kCFPreferencesCurrentHost // Safely read phone numbers with explicit user/host context let phones = CFPreferencesCopyAppValue("phoneArray" as CFString, appGroupID, currentUser, currentHost) as? [CXCallDirectoryPhoneNumber] ?? [] let names = CFPreferencesCopyAppValue("nameArray" as CFString, appGroupID, currentUser, currentHost) as? [String] ?? [] return (phones, names) }
Quick Additional Checks
To rule out other potential issues:
- Double-check your App Groups configuration: Both the main app and extension must have the exact same group ID enabled in "Signing & Capabilities", formatted like
group.your.bundle.identifier. - Confirm your phone numbers are still sorted in ascending order (you noted this is done, but it's a common silent failure point).
- Keep your extension logic lean: Avoid any slow operations in
addAllIdentificationPhoneNumbersorbeginRequest—the extension has a strict time limit during enablement, and delays will cause it to be rejected.
Why This Fixes It
By using CFPreferencesCopyAppValue with kCFPreferencesCurrentUser, you're aligning with the extension's sandbox requirements. This tells the system you're accessing preferences for the current user (not a generic "any user"), which is permitted for app group containers in non-system extensions.
内容的提问来源于stack exchange,提问作者Oliver

