在本机模块中找不到模块



我正在尝试使用本机代码在react-native(0.53.3(中实现iCloudStorage。 现在我有以下内容:

页眉

#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface iCloudStorage : RCTEventEmitter <RCTBridgeModule>
@end

#import "iCloudStorage.h"
#import <React/RCTEventDispatcher.h>
static NSString* const ICLOUDSTORAGE_PREFIX = @"@com.manicakes.iCloudStorage/";
static NSString* const ICLOUD_STORE_CHANGED = @"ICLOUD_STORE_CHANGED";
static NSString* const kStoreChangedEvent = @"iCloudStoreDidChangeRemotely";
static NSString* const kChangedKeys = @"changedKeys";
@implementation iCloudStorage
RCT_EXPORT_MODULE()

+ (NSString*)appendPrefixToKey:(NSString*)key {
return [NSString stringWithFormat:@"%@%@", ICLOUDSTORAGE_PREFIX, key];
}
+ (NSString*)removePrefixFromKey:(NSString*)key {
if (![key hasPrefix:ICLOUDSTORAGE_PREFIX]) {
return nil;
}
return [key substringFromIndex:[ICLOUDSTORAGE_PREFIX length]];
}
+ (NSDictionary*)storeDictionary {
NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
return [store dictionaryRepresentation];
}
+ (NSArray*)allKeysInStore {
return [[iCloudStorage storeDictionary] allKeys];
}
+ (id) getObjectForKey:(NSString*)key {
return [[NSUbiquitousKeyValueStore defaultStore] objectForKey:[iCloudStorage appendPrefixToKey:key]];
}
+ (void) setValue:(NSString*)value forKey:(NSString*)key {
[[NSUbiquitousKeyValueStore defaultStore] setObject:value forKey:[iCloudStorage appendPrefixToKey:key]];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
+ (void) removeKey:(NSString*)key {
[[NSUbiquitousKeyValueStore defaultStore] removeObjectForKey:[iCloudStorage appendPrefixToKey:key]];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
+ (NSString*) getMergedItemWithKey:(NSString*)key value:(NSString*)value rejecter:(RCTPromiseRejectBlock)reject {
NSDictionary* storedItem = @{};
NSDictionary* newItem = @{};
NSString* storedString = [iCloudStorage getObjectForKey:key];
if (storedString != nil) {
NSError* error = nil;
id object = [NSJSONSerialization JSONObjectWithData:[storedString dataUsingEncoding:NSUTF8StringEncoding]
options:0
error:&error];
if (error != nil) {
reject(@"json_decode_err", @"Error parsing stored value as JSON string.", error);
return nil;
}
if (![object isKindOfClass:[NSDictionary class]]) {
reject(@"json_not_object_err", @"The stored JSON string does not parse into an object.", nil);
return nil;
}
if (value != nil) {
id newObject = [NSJSONSerialization JSONObjectWithData:[value dataUsingEncoding:NSUTF8StringEncoding]
options:0
error:&error];
if (error != nil) {
reject(@"json_decode_err", @"The provided value is not valid JSON.", error);
return nil;
}
if (![newItem isKindOfClass:[NSDictionary class]]) {
reject(@"json_not_object_err", @"The provided JSON string does not parse into an object.", nil);
return nil;
}
newItem = newObject;
}
storedItem = object;
}
NSMutableDictionary* mergedItem = [NSMutableDictionary dictionaryWithDictionary:storedItem];
[mergedItem addEntriesFromDictionary:newItem];
NSError* error = nil;
NSData* data = [NSJSONSerialization dataWithJSONObject:mergedItem options:0 error:&error];
if (error != nil) {
reject(@"json_encode_err", @"Error encoding the merged JSON data to string.", error);
return nil;
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
- (instancetype)init {
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(ubiquitousStoreUpdated:)
name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
object:nil];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
return self;
}
- (NSArray<NSString *> *)supportedEvents {
return @[ kStoreChangedEvent ];
}
- (void) ubiquitousStoreUpdated:(NSNotification*)notification {
// if this notification comes in before bridge has initialized,
// don't try to send the event (app crashes if you do).
if (!self.bridge) {
return;
}
NSArray* changedKeys = [[notification userInfo] objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey];
NSMutableArray* reportedChangedKeys = [NSMutableArray array];
for (NSString* key in changedKeys) {
NSString* reportedKey = [iCloudStorage removePrefixFromKey:key];
if (reportedKey) {
[reportedChangedKeys addObject:reportedKey];
}
}
if ([reportedChangedKeys count]) {
NSDictionary* body = @{ kChangedKeys : reportedChangedKeys };
[self sendEventWithName:kStoreChangedEvent body:body];
}
}
RCT_EXPORT_METHOD(getItem: (NSString*)key resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
resolve([iCloudStorage getObjectForKey:key]);
}
RCT_EXPORT_METHOD(setItem: (NSString*)key value: (NSString*)value resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
[iCloudStorage setValue:value forKey:key];
resolve(@{});
}
RCT_EXPORT_METHOD(removeItem: (NSString*)key resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
[iCloudStorage removeKey:key];
resolve(@{});
}
RCT_EXPORT_METHOD(mergeItem: (NSString*)key value: (NSString*)value resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString* newValue = [iCloudStorage getMergedItemWithKey:key value:value rejecter:reject];
if (newValue == nil) {
// we failed and reject block was called.
return;
}
[iCloudStorage setValue:newValue forKey:key];
resolve(@{});
}
RCT_REMAP_METHOD(clear, clearResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
for (NSString* key in [iCloudStorage allKeysInStore]) {
if ([key hasPrefix:ICLOUDSTORAGE_PREFIX]) {
[[NSUbiquitousKeyValueStore defaultStore] removeObjectForKey:key];
}
}
resolve(@{});
}
RCT_REMAP_METHOD(getAllKeys, getAllKeysResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSMutableArray* allKeys = [NSMutableArray array];
for (NSString* storeKey in [iCloudStorage allKeysInStore]) {
NSString* key = [iCloudStorage removePrefixFromKey:storeKey];
if (key != nil) {
[allKeys addObject:key];
}
}
resolve(allKeys);
}
RCT_EXPORT_METHOD(multiGet: (NSArray*)keys resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[keys count]];
for (NSString* key in keys) {
NSObject* object = [iCloudStorage getObjectForKey:key];
if (object != nil) {
[result addObject:object];
}
}
resolve(result);
}
RCT_EXPORT_METHOD(multiSet: (NSDictionary*)keyValuePairs resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
for (NSString* key in [keyValuePairs allKeys]) {
[iCloudStorage setValue:[keyValuePairs objectForKey:key] forKey:key];
}
resolve(@{});
}
RCT_EXPORT_METHOD(multiRemove: (NSArray*)keys resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
for (NSString* key in keys) {
[iCloudStorage removeKey:key];
}
resolve(@{});
}
RCT_EXPORT_METHOD(multiMerge: (NSDictionary*)keyValuePairs resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:[keyValuePairs count]];
BOOL failed = NO;
for (NSString* key in [keyValuePairs allKeys]) {
NSString* newValue = [iCloudStorage getMergedItemWithKey:key value:[keyValuePairs objectForKey:key] rejecter:reject];
if (newValue == nil) {
break;
}
}
if (failed) {
return;
}
for (NSString* key in [result allKeys]) {
[iCloudStorage setValue:[result objectForKey:key] forKey:key];
}
resolve(@{});
}
- (NSDictionary<NSString *,id> *)constantsToExport {
return @{ ICLOUD_STORE_CHANGED : kStoreChangedEvent };
}
+ (BOOL)requiresMainQueueSetup {
return TRUE;
}
@end

问题是当我导入它时,它没有显示在NativeModules中。它返回undefined。 我错过了什么?我使用RCT_EXPORT_MODULE()导出它,并且我有requiresMainQueueSetup来抑制警告Module RCTImageLoader requires main queue setup since it overrides初始化but doesn't implement需要MainQueueSetup. In a future release React Native will default to initializing all native modules on a background thread unless explicitly opted-out of。 我一直在寻找,但在任何地方都找不到答案。 我已将文件添加到以项目命名的文件夹中:

<projectfolder>
--<projectName>
iCloudStorage.h
iCloudStorage.m
--libraries
--etc..

感谢您的帮助!

只需确保您的文件位于iOS文件夹中即可。 尝试使简单的导出模块工作,然后根据需要对其进行修改。

不要忘记在修改iOS本机文件后使用xCode或控制台重新构建。

一个简单的导出本机模块应如下所示(根据 RN 文档(:

// CalendarManager.h
#import <React/RCTBridgeModule.h>
@interface CalendarManager : NSObject <RCTBridgeModule>
@end
// CalendarManager.m
#import "CalendarManager.h"
@implementation CalendarManager
// To export a module named CalendarManager
RCT_EXPORT_MODULE();
// This would name the module AwesomeCalendarManager instead
// RCT_EXPORT_MODULE(AwesomeCalendarManager);
@end

然后尝试将其导入您的 RN 代码:

import {NativeModules} from 'react-native';
var CalendarManager = NativeModules.CalendarManager;

源: https://facebook.github.io/react-native/docs/native-modules-ios

您的项目树可能如下所示:

<projectfolder>
--<projectName>
--<ios>
iCloudStorage.h
iCloudStorage.m
--<android>
--JS libraries
--JS files etc

关于requiresMainQueueSetup警告:

如果它位于本机模块中,通常更新这些模块应该可以工作。

如果警告与您的代码相关,则必须按如下方式修改模块:

对于 Swift:

@objc(MyModule)
class MyModule: NSObject {
// ADD the 3 lines from below:
@objc static func requiresMainQueueSetup() -> Bool {
return false
}

对于目标C:

+ (BOOL)requiresMainQueueSetup
{
return NO;
}

只需根据模块需要的内容设置返回值即可。通常,如果您的模块不与 UI 交互,则 NO 就足够了。

最新更新