Мне нужно получить доступ к данным, хранящимся в AsyncStorage, из собственного кода Objective C. iOS.
Это необходимо, чтобы синхронизировать данные вместо отправки события приложения в JS, а затем отправить его обратно в собственный код.
Мне нужно получить доступ к данным, хранящимся в AsyncStorage, из собственного кода Objective C. iOS.
Это необходимо, чтобы синхронизировать данные вместо отправки события приложения в JS, а затем отправить его обратно в собственный код.
Я только что столкнулся с той же проблемой.
Мое решение состояло в том, чтобы переместить исходную сторону кода.
В 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 для выполнения этого синхронно
Update:
Мне нужна переменная в глобальном состоянии, а не только в компонентах реквизита, поэтому приведенное выше не достаточно далеко.
Мне пришлось работать в источнике React Native в том месте, где загружен источник Javascript.
NSString *javascriptPrepend = [NSString stringWithFormat:@"var ThemeMode = '%@';", self.theme];
NSMutableData *prependData = [[javascriptPrepend dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
[prependData appendData:sourceCode];
sourceCode = prependData;
Я посмотрю, открыты ли они для PR, чтобы разрешить такую функциональность и вернуться сюда, если я получу ее.
Усовершенствование решения @lukes - устранение проблемы с расположением данных в 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];
});
}
Мое текущее решение. Что технически не является прямым ответом на вопрос, но предлагает обход для обмена данными между Javascript и собственным кодом, заключается в использовании NSUserDefaults.
Используя этот пакет, response-native-default-preferences, чтобы легко сохранить данные в NSUserdefaults, а затем на родной стороне легко восстановить их как обычно.
В моих целях я сохраняю токен, полученный в Javascript, который будет использоваться позже расширениями приложения. Это означает, что я также сохраняю пакет UserDefaults, используя тот же ключ, что и мое приложение.
React Native (Javascript):
DefaultPreference.setName('group.myApp');
DefaultPreference.set('TOKEN', token);
Objective-C:
NSString *TOKEN = [[[NSUserDefaults alloc] initWithSuiteName:@"group.myApp"] stringForKey:@"TOKEN"];
Я думаю, что для этой цели вы можете использовать код из реализации AsyncStorage
. Вы можете увидеть здесь здесь. Он в основном загружает файлы, хранящие данные, с помощью NSFileManager
, а затем анализирует их соответственно. В вашем случае обратите внимание, например, на метод multiGet
и затем проследите все необходимые функции, присутствующие в файле. С этим вы должны иметь возможность повторно реализовать их (или адаптировать) в соответствии с вашими потребностями.