RCTRootView 多入口初始化白屏問題

查看RCTRootView 源碼可以看到有兩個初始化方法,在有多個
RCTRootView 初始化,也就是多個入口的情況,RN建議使用''initWithBridge:moduleName:''作為初始化方法。

/**
 * - Designated initializer -
 */
- (instancetype)initWithBridge:(RCTBridge *)bridge
                    moduleName:(NSString *)moduleName
             initialProperties:(NSDictionary *)initialProperties NS_DESIGNATED_INITIALIZER;

/**
 * - Convenience initializer -
 * A bridge will be created internally.
 * This initializer is intended to be used when the app has a single RCTRootView,
 * otherwise create an `RCTBridge` and pass it in via `initWithBridge:moduleName:`
 * to all the instances.
 */
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
                       moduleName:(NSString *)moduleName
                initialProperties:(NSDictionary *)initialProperties
                    launchOptions:(NSDictionary *)launchOptions;

/**
 * The name of the JavaScript module to execute within the
 * specified scriptURL (required). Setting this will not have
 * any immediate effect, but it must be done prior to loading
 * the script.
 */

常規(guī)情況,RN程序單個入口 不在介紹
多入口情況下,需要初始化一個RCTBridge 對象
查看RCTBridge 源碼發(fā)現(xiàn)

/**
 * Creates a new bridge with a custom RCTBridgeDelegate.
 *
 * All the interaction with the JavaScript context should be done using the bridge
 * instance of the RCTBridgeModules. Modules will be automatically instantiated
 * using the default contructor, but you can optionally pass in an array of
 * pre-initialized module instances if they require additional init parameters
 * or configuration.
 */
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
                   launchOptions:(NSDictionary *)launchOptions;

/**
 * DEPRECATED: Use initWithDelegate:launchOptions: instead
 *
 * The designated initializer. This creates a new bridge on top of the specified
 * executor. The bridge should then be used for all subsequent communication
 * with the JavaScript code running in the executor. Modules will be automatically
 * instantiated using the default contructor, but you can optionally pass in an
 * array of pre-initialized module instances if they require additional init
 * parameters or configuration.
 */
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
                   moduleProvider:(RCTBridgeModuleProviderBlock)block
                    launchOptions:(NSDictionary *)launchOptions;

/**

其中第二個初始化方法已經棄用。

使用方法 RN中文網給出如下解釋
http://reactnative.cn/docs/0.47/native-modules-ios.html

id<RCTBridgeDelegate> moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];

RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:nil];

RCTRootView *rootView = [[RCTRootView alloc]
                        initWithBridge:bridge
                            moduleName:kModuleName
                     initialProperties:nil];
id<RCTBridgeDelegate> moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];

這個classThatImplementsRCTBridgeDelegate 不是很清晰
這里其實就是 一個實現(xiàn)RCTBridgeDelegate協(xié)議的類
查看RCTBridgeDelegate 源碼


@protocol RCTBridgeDelegate <NSObject>

/**
 * The location of the JavaScript source file. When running from the packager
 * this should be an absolute URL, e.g. `http://localhost:8081/index.ios.bundle`.
 * When running from a locally bundled JS file, this should be a `file://` url
 * pointing to a path inside the app resources, e.g. `file://.../main.jsbundle`.
 */
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge;

有一個sourceURLForBridge 方法

所以我們新建一個類遵循RCTBridgeDelegate代理方法,實現(xiàn)sourceURLForBridge方法

#import <Foundation/Foundation.h>
#import <React/RCTBridgeDelegate.h>
#import <React/RCTBridge.h>

@interface MallBridgeAPI : RCTBridge
/** 單例 */
+ (MallBridgeAPI *)shareInstance;
@end

@interface MallBridgeHandle : NSObject<RCTBridgeDelegate>

@end

#import "MallBridgeAPI.h"


@implementation MallBridgeAPI
static MallBridgeAPI *defaultHandle = nil;
+ (MallBridgeAPI *)shareInstance
{
    @synchronized(self){
        if (defaultHandle == nil) {
            defaultHandle = [[MallBridgeAPI alloc] initWithDelegate:[[MallBridgeHandle alloc]init] launchOptions:nil];
        }
    }
    return defaultHandle;
}
@end


@implementation MallBridgeHandle

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
    return [NSURL URLWithString:@"http://127.0.0.1:8081/index.ios.bundle?platform=ios"];
#else
    return [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
#endif
    
}
@end

至此 RCTBridge 實例,即可 使用classThatImplementsRCTBridgeDelegate 完成初始化

  
self.rootView = [[RCTRootView alloc]initWithBridge:[MallBridgeAPI shareInstance]
                                          moduleName:@"MyShopVC"
                                   initialProperties:@{@"schemeType":@"debug",@"isSelectedProvider":@(isSelectedProvider)}];
  
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容