RCTRootView 多入口初始化问题

作者: _海角_ | 来源:发表于2017-08-08 12:49 被阅读356次

    查看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.
     */
    

    常规情况,RN程序单个入口 不在介绍
    多入口情况下,需要初始化一个RCTBridge 对象
    查看RCTBridge 源码发现

    /**
     * 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 不是很清晰
    这里其实就是 一个实现RCTBridgeDelegate协议的类
    查看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代理方法,实现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)}];
    
    

    相关文章

      网友评论

      • 32de70a256cd:看了上面的代码,先用到了单例,再初始化一个handle,为何不直接设置代理为单例自己呢?
      • _海角_:js那边还是正常开发,之前怎么做,现在还怎么做
      • bomo:那js方面,如何获取到这个bridge,如何调用bridge的方法

      本文标题:RCTRootView 多入口初始化问题

      本文链接:https://www.haomeiwen.com/subject/bbdtrxtx.html