从ios本机代码访问存储在AsyncStorage中的数据(目标c)

时间:2016-10-17 16:21:13

标签: ios objective-c react-native

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

这需要使数据同步,而不是将App事件发送给JS,然后将其发送回本机代码。

4 个答案:

答案 0 :(得分:4)

我刚遇到同样的问题。

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

在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以允许这种功能,如果我通过它就会回到这里。

答案 1 :(得分:1)

增强@ 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];
  });
}

答案 2 :(得分:1)

我目前的解决方案。从技术上讲,这不是问题的直接答案,但提供了在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"];

答案 3 :(得分:-1)

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