如何在Swift开发的Apple Watch中访问React Native iOS的AsyncStorage数据
首先得明确:真机上iOS主应用和Watch应用的沙盒是完全隔离的,你在模拟器里找到的那个manifest.json路径,真机上Watch app根本访问不到——所以直接读文件的方法只能用来临时调试,正式上线必须用苹果提供的跨应用共享机制。下面给你两个最实用的方案:
方案一:用App Groups共享存储(适合静态参数读取)
这个方法是把需要共享的数据放到主应用和Watch app都能访问的共享容器里,步骤很清晰:
1. 开启App Groups权限
打开Xcode,分别给主iOS应用和Watch Extension添加同一个App Group:
- 选中目标应用 → 进入
Signing & Capabilities标签 → 点击+ Capability→ 搜索并添加App Groups - 在App Groups里添加一个唯一的标识,比如
group.com.yourcompany.yourapp.shared(两个应用必须用同一个标识)
2. 在React Native里同步数据到共享容器
因为原生的AsyncStorage默认存在主应用自己的沙盒里,所以我们需要把要共享的数据同步到App Groups的UserDefaults里(或者直接修改AsyncStorage的存储路径到共享容器,不过同步到UserDefaults更简单)。
第一步:写一个RN原生模块(Swift)
在iOS项目里新建一个Swift文件,比如SharedStorage.swift:
import Foundation import React @objc(SharedStorage) class SharedStorage: NSObject, RCTBridgeModule { // 模块名称,RN里要用到 static func moduleName() -> String! { return "SharedStorage" } static func requiresMainQueueSetup() -> Bool { return true } // 保存数据到共享UserDefaults @objc func saveItem(_ key: String, value: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { guard let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp.shared") else { reject("GROUP_ERROR", "无法访问共享容器", nil) return } sharedDefaults.set(value, forKey: key) sharedDefaults.synchronize() resolve(nil) } // 从共享UserDefaults读取数据 @objc func getItem(_ key: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { guard let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp.shared") else { reject("GROUP_ERROR", "无法访问共享容器", nil) return } let value = sharedDefaults.string(forKey: key) resolve(value) } }
第二步:在RN里调用这个模块
在RN代码里封装一下,方便调用:
import { NativeModules } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; const { SharedStorage } = NativeModules; // 保存数据时,同时存到AsyncStorage和共享容器 export const saveSharedData = async (key, value) => { try { await Promise.all([ AsyncStorage.setItem(key, value), SharedStorage.saveItem(key, value) ]); } catch (error) { console.error('保存共享数据失败:', error); } }; // 从共享容器读取数据 export const getSharedData = async (key) => { try { const value = await SharedStorage.getItem(key); return value; } catch (error) { console.error('读取共享数据失败:', error); return null; } };
3. 在Watch app里读取数据
在Swift写的Watch app代码里,直接访问共享的UserDefaults:
guard let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp.shared") else { // 处理无法访问的情况 return } // 读取你需要的参数 let requestParam = sharedDefaults.string(forKey: "your_param_key")
方案二:用Watch Connectivity同步数据(适合实时更新/双向通信)
如果你的数据需要实时同步,或者主app和Watch app需要互相传数据,用苹果的WatchConnectivity框架更合适:
1. 开启Watch Connectivity
分别在主应用和Watch Extension里初始化WCSession:
主应用(AppDelegate.swift)
import WatchConnectivity class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 初始化Watch连接 if WCSession.isSupported() { let session = WCSession.default session.delegate = self session.activate() } return true } // 必须实现的代理方法 func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {} }
Watch Extension(ExtensionDelegate.swift)
import WatchConnectivity class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate { func applicationDidFinishLaunching() { if WCSession.isSupported() { let session = WCSession.default session.delegate = self session.activate() } } func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {} }
2. 在RN里发送数据到Watch
同样写一个原生模块来调用Watch Connectivity:
import Foundation import React import WatchConnectivity @objc(WatchSync) class WatchSync: NSObject, RCTBridgeModule { static func moduleName() -> String! { return "WatchSync" } static func requiresMainQueueSetup() -> Bool { return true } // 发送数据到Watch @objc func sendData(_ data: [String: Any], resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) { guard WCSession.default.isReachable else { reject("WATCH_UNREACHABLE", "Watch未连接", nil) return } do { try WCSession.default.updateApplicationContext(data) resolve(nil) } catch { reject("SYNC_FAILED", "同步失败", error) } } }
RN里调用:
import { NativeModules } from 'react-native'; const { WatchSync } = NativeModules; // 当AsyncStorage的数据更新时,同步到Watch export const syncToWatch = async (key, value) => { try { await WatchSync.sendData({ [key]: value }); } catch (error) { console.error('同步到Watch失败:', error); } };
3. 在Watch app里接收数据
在Watch Extension的代理里实现接收方法:
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { DispatchQueue.main.async { // 处理接收到的数据,比如更新UI或者保存到本地 if let param = applicationContext["your_param_key"] as? String { // 用这个参数发起请求 } } }
临时调试方案(仅模拟器可用)
如果你只是在模拟器里测试,不想改代码,可以直接读取你找到的manifest.json文件,但真机上绝对不能用:
// 替换成你模拟器的设备ID和应用ID let deviceID = "D10E869B-040B-446F-9B8B-754F111442EC" let appID = "AC837AFE-312B-4861-906D-EC9EEE7D029B" let filePath = "/Users/你的用户名/Library/Developer/CoreSimulator/Devices/\(deviceID)/data/Containers/Data/Application/\(appID)/Documents/RCTAsyncLocalStorage_V1/manifest.json" if let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { let desiredValue = json["你的参数key"] as? String // 使用这个值 }
内容的提问来源于stack exchange,提问作者João Belo

