美文网首页RN iOS开发相关
新手入门 React-Native 开发iOS原生和React-

新手入门 React-Native 开发iOS原生和React-

作者: ZeroSmell | 来源:发表于2018-04-01 12:31 被阅读372次

    1.callback回调方式,RN触发事件回调iOS原生的数据

    例如代码:  

    io部分代码

    //定义导出的模块名

    RCT_EXPORT_MODULE()

    //定义导出的方法名

    RCT_EXPORT_METHOD(pushEvent:(NSString *)event callback:(RCTResponseSenderBlock)callback){

      NSLog(@"----对React Native提供调用方法,Callback---%@",event);

      NSString *callbackData = @"原生数据被RN调用"; //准备回调回去的数据

      callback(@[[NSNull null],callbackData]);

    }

    React-Native引用

    var ZeroCallbackModule = NativeModules.ZeroCallbackModule;

    <Txet 自己设置大小样式>

         onPress={()=>this.callBackEvent()}>

           {/*callback-方式点击调原生+回调*/}

    </Text>

    实现rn和iOS通信回调

    callBackEvent (){

    ZeroCallbackModule.pushEvent(('RN->原生的数据'),(error, events) => {

    if (error) {

    console.log(error);

        }else {

    alert(events)//返回的数据

        }

    })

    }

    2.promise实现的回调函数我自己的理解类似于iOS的block回调方式。。。新手理解!!

    iOS部分代码

    static RCTPromiseResolveBlock _resolve;

    static RCTPromiseRejectBlock _reject;

    RCT_REMAP_METHOD(pushPromisesEvent,

                    resolver:(RCTPromiseResolveBlock)resolve

                    rejecter:(RCTPromiseRejectBlock)reject){

      _resolve = resolve;

      _reject = reject;

      [[ZeroHttpRquestManager sharedManager]requestPostWithPath:@"http" completed:^(BOOL ret, id obj) {

              [ZeroCallbackModule handleResult:obj];

      }];

    }

    +(void) handleResult:(id)result{

      //原生Promises数据被RN调用

      if ([result isEqualToString:@"获取数据成功"]) {

        _resolve(@[result]);

      }else{

        //返回错误信息

        NSError *error=[NSError errorWithDomain:result code:101 userInfo:nil];

          _reject(@"no_events", @"There were no events", error);

      }

    }

    RCT_REMAP_METHOD(promisesEvent,

                    presolver:(RCTPromiseResolveBlock)resolve

                    prejecter:(RCTPromiseRejectBlock)reject){

      NSString *PromisesData = @"原生Promises数据被RN调用";

      if (PromisesData) {

            resolve(PromisesData);

      } else {

        NSError *error=[NSError errorWithDomain:@"我是Promise回调错误信息..." code:101 userInfo:nil];

        reject(@"no_events", @"There were no events", error);

      }

    }

    rn引用代码实现

    <Text   自己设置大小样式

    onPress={()=>this.promisesEvent()}>

     Promise回调-方式

    </Text>

    async promisesEvent(){

    ZeroCallbackModule.pushPromisesEvent().then((events)=>{

    alert(events+1111)

    }).catch((e)=>{

    // alert(e)

            console.log("错误信息------"+e);

      })

    }

    3.类似iOS的通知模式 RCTEventEmitter

    1.继承这个类

    @interface ZeroBridgeEventEmitter : RCTEventEmitter

    @end

    2.iOS代码实现

    - (NSArray *)supportedEvents{

        return@[@"data ",@"callback ",@"event"];

    }

    //发送消息代码。。在iOS端自己做一个触发事件处理

    -(void)message:(NSString*)callback  event:(NSString*)event    target:(id)target{

      [self sendEventWithName:@"onChange"

                        body:@{

                                @"callback": callback,

                                @"event": event,

                              @"target":target,

                                }];

    }

    3.RN引用代码(如果引用有坑。。就是iOS端做一个触发事件去触发)

    componentDidMount(){

          NativeModule.addListener('onChange',(data)=>this.message(data));

    }

    message (data) {//body 看你传什么

      console.log('————————————————————'+data);

      alert('hahhaahah');

    }

    componentWillUnmount() {

    //删除监听

      this.NativeModule.remove()

    }

    4.关键是在于RN引用的问题。。。网上例子很多的。。但是真正自己去使用的时候发现存在有问题。。我说下我们公司的项目。。是H5写的项目嵌入到RN中使用。。但是还必须自己在iOS端自定义一个UIWebView来加载H5的页面运行。。。所以我自己还是遇到了很多的坑的。。。发现这个方法使用的话。。不适合自己项目的场景。。而且之前android端定义好了很多方法和实现方式。。导致我很被动的只能按照那种方式实现。。。

    iOS端自定义的UIWebView通过继承于RCTViewManager的类给RN使用

    倒入头文件类

    @interface ZeroBridgeWebViewManager ()

    @property (nonatomic, strong) RCTBridge *bridge;

    @end

    @implementation ZeroBridgeWebViewManager

    RCT_EXPORT_MODULE(ZeroBridgeWebViewManager)

    这里是原生的属性给rn使用

    RCT_EXPORT_VIEW_PROPERTY(statusBarHeight, NSInteger)RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL)RCT_EXPORT_VIEW_PROPERTY(isNotice, BOOL)RCT_EXPORT_VIEW_PROPERTY(bottomNavHeight, NSInteger)RCT_EXPORT_VIEW_PROPERTY(currentPage, NSDictionary)RCT_EXPORT_VIEW_PROPERTY(url, NSString)

    /**重写这个方法,返回将要提供给RN使用的视图*/

    - (UIView *)view { ZeroBridgeWebView*view = [[ZeroBridgeWebView alloc]initWithFrame:[UIScreen mainScreen].bounds];

     view.delegate = self;

     return view;

    }

    /**获取当前试图View*/

    - (ZeroBridgeWebView*) getViewWithTag:(NSNumber *)tag {

     NSLog(@"%@", [NSThread currentThread]);

     UIView *view = [self.bridge.uiManager viewForReactTag:tag];

     return [view isKindOfClass:[ZeroBridgeWebView class]] ? (ZeroBridgeWebView *)view : nil;

    }

    /**当前显示线程队列*/

    - (dispatch_queue_t)methodQueue

    { return dispatch_get_main_queue();

     }

    - (NSArray *)supportedEvents

    {

      /**注意最坑的就是这了。。。在RN中引用UIWebView的方法是onMessage他在这里要写成topMessage*/

      return @[@"topMessage"];

    }

    #pragma mark-这里是点击webView代理回调事件

    - (void)webView:(UIWebView *)webView didFinishLoad:(NSURL *)load{

      /**很坑的这个topMessage*/

      [self.bridge.eventDispatcher sendAppEventWithName:@"topMessage"

                                                  body:@{

                                                          @"code": @"发送的参数",

                                                          @"result": @"发送的参数",

                                                          @"body": @"发送的参数",

                                                          }];

    }

    var RCBridgeWebView = requireNativeComponent('ZeroBridgeWebView', BridgeWebView);

    export default class BridgeWebView extends Component {

    // 与OC中 RCTViewManager子类中导出的属性对应

        static propTypes = {

    value:                      React.PropTypes.number,

            isTest1:                    React.PropTypes.bool,

            num:                        React.PropTypes.number,

            infoDict:                  React.PropTypes.object,

            url:                        React.PropTypes.string,

        };

        componentDidMount() {

    console.log("MyView被加载了");

        }

    render() {

    return(

    <RCBridgeWebView onMessage={()=>this.onMessage()}>

    </RCBridgeWebView>

            );

        }

    }

    //这个坑害了我好久的。。

    onMessage(){

    }

    5.一些遇到的其他的坑。。也是网上找了半天才解决的。。。

    1.Duplicate interface definition for class 'RCTView' 或者类似的错误都这样解决

    这个错误解决办法:#import "RCTView.h" 替换成 #import<React/RCTView.h>

    2.出现错误 ld: library not found for -lRNDeviceInfo-tvOS或者类似的错误。。

    clang: error: linker command failed with exit code 1 (use -v to see invocation) 这个错误

    解决办法: 删掉这个库文件在

    3.出现问题解决Xcode中 RSKImageCropper.framework和QBImagePicker.framework报错问题

    http://blog.csdn.net/u013718120/article/details/72781285

    4.还有一些其他的混合问题。。各种引用的问题。。私信我有时间给你下回答。。

    相关文章

      网友评论

        本文标题:新手入门 React-Native 开发iOS原生和React-

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