【问题标题】:Access data stored in AsyncStorage from ios native code (objective c)从 ios 本机代码访问存储在 AsyncStorage 中的数据(目标 c)
【发布时间】:2017-02-26 17:21:51
【问题描述】:

我需要从 iOS 原生 Objective C 代码访问存储在 AsyncStorage 中的数据。

这是同步数据所必需的,而不是向 JS 发送 App 事件,然后将其发送回本机代码。

【问题讨论】:

  • 你有没有想过这个问题?

标签: ios objective-c react-native


【解决方案1】:

我认为您可以为此目的使用实现 AsyncStorage 中的代码。你可以看到它here。它基本上使用NSFileManager 加载存储数据的文件,然后相应地解析它们。在您的情况下,例如查看multiGet method,然后跟踪文件中存在的所有必需函数。有了它,您应该能够重新实现(或适应)它们以满足您的需求。

【讨论】:

    【解决方案2】:

    我也遇到了同样的问题。

    我的解决方案是移动代码原生端。

    在 iOS 上:

    #import <React/RCTAsyncLocalStorage.h>
    #import <React/RCTBridgeModule.h>
    
    RCTResponseSenderBlock completion = ^(NSArray *response) {
      NSString *theme = response[1][0][0][1];
    
      // Setup RCTRootView with initialProperties
    };
    
    RCTAsyncLocalStorage *storage = [[RCTAsyncLocalStorage alloc] init];
    
    dispatch_async(storage.methodQueue, ^{
      [storage performSelector:@selector(multiGet:callback:) withObject:@[@"theme"] withObject:completion];
    });
    

    您还可以使用 dispatch_semaphore_wait 同步执行此操作

    更新:

    我需要全局状态中的变量,而不仅仅是在组件道具中,所以上面的内容还不够。

    在加载 Javascript 源代码时,我必须将它处理到 React Native 源代码中。

    NSString *javascriptPrepend = [NSString stringWithFormat:@"var ThemeMode = '%@';", self.theme];
    NSMutableData *prependData = [[javascriptPrepend dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
    [prependData appendData:sourceCode];
    
    sourceCode = prependData; 
    

    我会看看他们是否对 PR 开放以允许这种功能,如果我通过了,我会在此处回复。

    【讨论】:

      【解决方案3】:

      增强@luke 的解决方案——修复response 中数据位置的问题;将 JSON 数据转换为 NSDictionary 并确保代码的安全性——这是完整的方法:

      +(void)jsonFromLocalRNStrogeForKey:(NSString *)key completion:(void (^)(NSDictionary * _Nullable, NSError * _Nullable))completion
      {
        RCTResponseSenderBlock rnCompletion = ^(NSArray *response) {
      
          NSString *jsonAsString;
      
          if (response.count > 1) {
            NSArray *response1 = response[1];
            if (response1.count > 0) {
              NSArray *response2 = response1[0];
      
              if (response2.count > 1) {
                jsonAsString = response2[1];
              }
            }
          }
      
          NSData *jsonAsData = [jsonAsString dataUsingEncoding:NSUTF8StringEncoding];
      
          NSError *error;
      
          NSDictionary *json = [NSJSONSerialization
                                JSONObjectWithData:jsonAsData                                                          options:NSJSONReadingMutableContainers                                                             error:&error];
      
          completion(json, error);
        };
      
        RCTAsyncLocalStorage *storage = [RCTAsyncLocalStorage new];
      
        dispatch_async(storage.methodQueue, ^{
          [storage performSelector:@selector(multiGet:callback:) withObject:@[key] withObject:rnCompletion];
        });
      }
      

      【讨论】:

      • 能否举例说明如何调用该方法?我需要对我在 Android 上所做的 same thing 做,但现在在 iOS 上做。
      • 假设您在一个名为 Utils 的类上定义了函数。然后让我们获取您之前存储的当前用户。然后你会这样做: [Utils jsonFromLocalRNStrogeForKey:@"USER_KEY" completion:^(NSDictionary * _Nullable json, NSError * _Nullable error) { // 对数据做一些事情 (json) }];
      • 这行得通,但我相信现在的问题是找到正确的根密钥。就像我说的,在 Android 上我从 catalystLocalStorage 开始,其中整个 data 仅作为 json 字符串 在第一行,而在 iOS 上我尝试了 usergroup.MyAppjsonAsString 它始终为空。你知道 iOS 的主要关键是什么吗?
      • Here,在我拥有的每一个可能的键中,我都得到了空值。
      • 你可以看看这个stackoverflow.com/questions/48280006/…吗?
      【解决方案4】:

      我目前的解决方案。从技术上讲,这不是问题的直接答案,但确实提供了在 Javascript 和本机代码之间共享数据的解决方法,即使用 NSUserDefaults。

      使用这个包,react-native-default-preferences 可以轻松地将数据保存到 NSUserdefaults 中,然后在本机端轻松地正常检索它们。

      出于我的目的,我将保存在 Javascript 中检索到的令牌,以供以后应用程序的扩展使用。这意味着我还坚持使用与我的应用相同的密钥的 UserDefaults 套件。

      React Native(Javascript):

      DefaultPreference.setName('group.myApp');
      DefaultPreference.set('TOKEN', token);
      

      目标-C:

      NSString *TOKEN = [[[NSUserDefaults alloc] initWithSuiteName:@"group.myApp"] stringForKey:@"TOKEN"];
      

      【讨论】:

      • group.myApp 是 iOS 使用的默认名称吗?如果应用名称是 TheApp,我应该致电 group.TheApp 吗?
      • 如果您在一组共享应用程序之间共享数据,您只需要设置名称。例如,共享扩展和您的主应用程序。您首先需要设置一个组,然后在初始化 NSUserDefaults 时,使用格式为 group.YOUR_APPS_NAME 的名称来访问相同的共享 NSUserDefaults。
      • 更多关于设置应用组的信息可以在这里找到blog.intrepid.io/ios-app-extensions
      • 嘿伙计!那么问题已解决herehere。不过还是谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      相关资源
      最近更新 更多