You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift开发的Apple Watch中访问React Native iOS的AsyncStorage数据

如何让Apple Watch应用获取React Native主应用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:10:01