美文网首页
XCode12.5 ReactNative0.6.2环境报错

XCode12.5 ReactNative0.6.2环境报错

作者: Tsnow308 | 来源:发表于2021-11-27 11:11 被阅读0次

    Cannot initialize a parameter of type ‘NSArray<id<RCTBridgeModule>>
    今天发现,XCode12.5上,打开RN某工程,环境报错,有两个方法,第一个方法在podfile文件里替换:

    post_install do |installer|
    ## Fix for XCode 12.5
      find_and_replace(
      "../node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm",
      "_initializeModules:(NSArray<id<RCTBridgeModule>> *)modules", 
      "_initializeModules:(NSArray<Class> *)modules")
      
      find_and_replace(
      "../node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm",
      "RCTBridgeModuleNameForClass(module))", 
      "RCTBridgeModuleNameForClass(Class(module)))"
      )
    end
    
    def find_and_replace(dir, findstr, replacestr)
      Dir[dir].each do |name|
          text = File.read(name)
          replace = text.gsub(findstr,replacestr)
          if text != replace
              puts "Fix: " + name
              File.open(name, "w") { |file| file.puts replace }
              STDOUT.flush
          end
      end
      Dir[dir + '*/'].each(&method(:find_and_replace))
    end
    

    然后pod install即可。

    第二个方法:如果没有podfile文件,可以直接替换RCTCxxBridge.mm里的- (void)registerAdditionalModuleClasses方法替换成:


    image.png

    RCTTurboModuleManager.mm文件里- (id<RCTTurboModule>)provideRCTTurboModule里出错的地方替换成:


    image.png

    保存,重新编译即可。
    2021.9.29 贴出源码:
    1.修改registerAdditionalModuleClasses的传入参数:

    - (void)registerAdditionalModuleClasses:(NSArray<Class> *)modules
    {
      std::lock_guard<std::mutex> guard(_moduleRegistryLock);
      if (_moduleRegistryCreated) {
        NSArray<RCTModuleData *> *newModules = [self _initializeModules:modules withDispatchGroup:NULL lazilyDiscovered:YES];
        assert(_reactInstance); // at this point you must have reactInstance as you already called reactInstance->initialzeBridge
        _reactInstance->getModuleRegistry().registerModules(createNativeModules(newModules, self, _reactInstance));
      } else {
        [self registerModulesForClasses:modules];
      }
    }
    

    RCTTurboModuleManager.mm文件文件里provideRCTTurboModule函数:

    - (id<RCTTurboModule>)provideRCTTurboModule:(const char *)moduleName
    {
      Class moduleClass;
      id<RCTTurboModule> module = nil;
    
      {
        std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
    
        auto rctTurboModuleCacheLookup = _rctTurboModuleCache.find(moduleName);
        if (rctTurboModuleCacheLookup != _rctTurboModuleCache.end()) {
          return rctTurboModuleCacheLookup->second;
        }
    
        if (_invalidating) {
          // Don't allow creating new instances while invalidating.
          return nil;
        }
    
        /**
         * Step 2a: Resolve platform-specific class.
         */
        if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
          moduleClass = [_delegate getModuleClassFromName:moduleName];
        }
    
        if (!moduleClass) {
          moduleClass = getFallbackClassFromName(moduleName);
        }
    
        if (![moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) {
          return nil;
        }
    
        /**
         * Step 2b: Ask hosting application/delegate to instantiate this class
         */
        if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
          module = [_delegate getModuleInstanceFromClass:moduleClass];
        } else {
          module = [moduleClass new];
        }
    
        if ([module respondsToSelector:@selector(setTurboModuleLookupDelegate:)]) {
          [module setTurboModuleLookupDelegate:self];
        }
    
        _rctTurboModuleCache.insert({moduleName, module});
      }
    
      /**
       * It is reasonable for NativeModules to not want/need the bridge.
       * In such cases, they won't have `@synthesize bridge = _bridge` in their
       * implementation, and a `- (RCTBridge *) bridge { ... }` method won't be
       * generated by the ObjC runtime. The property will also not be backed
       * by an ivar, which makes writing to it unsafe. Therefore, we check if
       * this method exists to know if we can safely set the bridge to the
       * NativeModule.
       */
      if ([module respondsToSelector:@selector(bridge)] && _bridge) {
        /**
         * Just because a NativeModule has the `bridge` method, it doesn't mean
         * that it has synthesized the bridge in its implementation. Therefore,
         * we need to surround the code that sets the bridge to the NativeModule
         * inside a try/catch. This catches the cases where the NativeModule
         * author specifies a `bridge` method manually.
         */
        @try {
          /**
           * RCTBridgeModule declares the bridge property as readonly.
           * Therefore, when authors of NativeModules synthesize the bridge
           * via @synthesize bridge = bridge;, the ObjC runtime generates
           * only a - (RCTBridge *) bridge: { ... } method. No setter is
           * generated, so we have have to rely on the KVC API of ObjC to set
           * the bridge property of these NativeModules.
           */
          [(id)module setValue:_bridge forKey:@"bridge"];
        } @catch (NSException *exception) {
          RCTLogError(
              @"%@ has no setter or ivar for its bridge, which is not "
               "permitted. You must either @synthesize the bridge property, "
               "or provide your own setter method.",
                RCTBridgeModuleNameForClass(Class(module)));
        }
      }
    
      /**
       * Some modules need their own queues, but don't provide any, so we need to create it for them.
       * These modules typically have the following:
       *   `@synthesize methodQueue = _methodQueue`
       */
      if ([module respondsToSelector:@selector(methodQueue)]) {
        dispatch_queue_t methodQueue = [module performSelector:@selector(methodQueue)];
        if (!methodQueue) {
          NSString *moduleClassName = NSStringFromClass(module.class);
          NSString *queueName = [NSString stringWithFormat:@"com.facebook.react.%@Queue", moduleClassName];
          methodQueue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
          @try {
            [(id)module setValue:methodQueue forKey:@"methodQueue"];
          } @catch (NSException *exception) {
            RCTLogError(
                @"TM: %@ is returning nil for its methodQueue, which is not "
                 "permitted. You must either return a pre-initialized "
                 "queue, or @synthesize the methodQueue to let the bridge "
                 "create a queue for you.",
                moduleClassName);
          }
        }
      }
    
      /**
       * Broadcast that this TurboModule was created.
       *
       * TODO(T41180176): Investigate whether we can get rid of this after all
       * TurboModules are rolled out
       */
      [[NSNotificationCenter defaultCenter]
          postNotificationName:RCTDidInitializeModuleNotification
                        object:_bridge
                      userInfo:@{@"module" : module, @"bridge" : RCTNullIfNil(_bridge.parentBridge)}];
      return module;
    }
    

    相关文章

      网友评论

          本文标题:XCode12.5 ReactNative0.6.2环境报错

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