如何在React Native Expo原生模块中使用Apple FamilyControls并解决报错
解决Expo原生模块中FamilyControls的4097错误及使用指南
问题重现
在Expo原生模块中导入FamilyControls时出现以下错误:
[FamilyControls] Failed to get service proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.FamilyControlsAgent" UserInfo={NSDebugDescription=connection to service named com.apple.FamilyControlsAgent}
当前模块代码实现:
import ExpoModulesCore import FamilyControls public class ExpoScreenTimeApiModule: Module { public func definition() -> ModuleDefinition { let center = AuthorizationCenter.shared Name("ExpoScreenTimeApi") AsyncFunction("requestScreenTimePermission") { () -> String in let center = AuthorizationCenter.shared do { try await center.requestAuthorization(for: .individual) return "Permission Granted" } catch { throw error // This will be caught as a Promise rejection in JavaScript. } } } }
解决方案及正确使用步骤
1. 必须使用真机测试
FamilyControls框架不支持iOS模拟器,模拟器中不存在com.apple.FamilyControlsAgent服务,直接触发4097错误,请切换到真实iOS设备调试。
2. 配置Info.plist权限
在iOS项目的Info.plist中添加屏幕时间权限描述,否则授权请求会被系统拒绝:
<key>NSFamilyControlsUsageDescription</key> <string>需要访问屏幕时间数据以管理应用使用时长</string>
替换字符串内容为你的应用实际需求说明。
3. 修正模块代码逻辑
移除definition()函数中提前声明的let center = AuthorizationCenter.shared,并优化授权流程(先检查状态再请求):
import ExpoModulesCore import FamilyControls public class ExpoScreenTimeApiModule: Module { public func definition() -> ModuleDefinition { Name("ExpoScreenTimeApi") AsyncFunction("requestScreenTimePermission") { () -> String in let center = AuthorizationCenter.shared // 先检查当前授权状态 switch center.authorizationStatus { case .authorized: return "Permission Already Granted" case .denied, .notDetermined: do { try await center.requestAuthorization(for: .individual) return "Permission Granted" } catch { throw error } @unknown default: throw NSError(domain: "ExpoScreenTimeApi", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown authorization status"]) } } // 新增方法获取当前授权状态 AsyncFunction("getAuthorizationStatus") { () -> String in let status = AuthorizationCenter.shared.authorizationStatus switch status { case .authorized: return "authorized" case .denied: return "denied" case .notDetermined: return "notDetermined" @unknown default: return "unknown" } } } }
4. 确保Expo环境配置正确
- 执行
expo prebuild生成原生项目文件,确认模块已在ExpoModules.plist中注册 - 使用Expo开发客户端(Expo Go不支持自定义原生模块)测试,或直接通过Xcode编译真机运行
内容的提问来源于stack exchange,提问作者Tezzus
相关产品推荐
相关产品推荐

