react native之App集成以及高度自適應

集成

與現有App集成,以及高度適應問題,官方文檔中都有說明,單拉一篇文章出來,主要是想記錄一下其中的問題點,給大家做些參考。

集成到現有App,無非是把react界面放到現有App中的某個頁面中,那么第一點是要把react native加到現有工程,第二點創建RCTRootView并添加到某頁面。

react native添加到現有工程,有兩種方式:

1、使用cocoapods,自動化管理;
2、手工集成,即將react native各個子工程手動添加到項目中;

但是,在此之前,還有一件至關重要的事:下載react native工程

react native使用node.js作為工程集成環境,包管理使用npm工具,所以這一步也比較簡單:

//在現有App工程目錄中創建package.json文件,執行npm install:
{
  "name": "reactDemo",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {
    "react": "^15.2.1",
    "react-native": "^0.29.2"
  }
}

當前目錄就會創建node_modules,react native所有依賴項都存在此目錄中。

使用cocoapods集成比較方便:

//創建podfile,配置工程依賴項,注意:path路徑要設置自己的node_modules正確路徑

target 'App工程名稱' do

  pod 'React', :path => './node_modules/react-native', :subspecs => [
    'Core',
    'RCTText',
    'RCTWebSocket', # needed for debugging
    # Add any other subspecs you want to use in your project
    'RCTImage',
    'RCTNetwork',
    'RCTActionSheet',
    'RCTGeolocation',
    'RCTLinkingIOS',
    'RCTVibration',
    'RCTSettings',
  ]

end

執行: pod install, 即可集成react native到現有工程。

手動添加react native,就要麻煩一下,進入node_modules目錄查找相應react工程,即project,將project添加到現有工程中即可。

下一步,創建react頁面,并作為子頁面添加到現有項目中:

    NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

    jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
    
    _rctView = [[RCTRootView alloc] initWithBundleURL: jsCodeLocation moduleName:@"reactDemo" initialProperties:@{} launchOptions:nil];
    
    [self.view addSubview: _rctView];

到這一步,算是整體集成完畢,可以啟動服務看頁面是否能正常展示。

react高度適應

react頁面高度是不定的,這就給react頁面的父頁面設定帶來一些問題。官方也給出了解決方案,就是父頁面使用UIScrollView,并監聽react頁面高度變化,使父頁面隨react頁面變化而變化。

設置監聽RCTRootView的高度變化:


    _rctView.delegate = self;
    _rctView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight;

#pragma mark - RCTRootViewDelegate
- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {

    CGRect newFrame = rootView.frame;
    newFrame.size = rootView.intrinsicSize;
    
    rootView.frame = newFrame;
    self.view.frame = newFrame;
    
    if (self.delegate) {
        [self.delegate didChangeHeight: newFrame.size.height];
    }
}    

ok,集成和高度適應都完畢了,下來還有什么問題?

touchable與UIScrollView事件沖突問題

這里說的事件沖突,倒不是說UIScrollView截獲了Touchable的點擊事件,而是Touchable會把UIScrollView的滾動事件誤認為是點擊事件。所以造成的現象就是,當滾動UIScrollView時,同時會出發Touchable點擊事件,這種體驗糟糕的不要不要的。

react native自身也封裝了ScrollView,在使用react native的ScrollView時不會存在這個問題,明顯react native發現并解決了該問題。react native的點擊事件又必須依賴Touchable,我們又不能使用react native的ScrollView,所以這個問題不能靠框架解決。

解決思路:

Touchable是完全依賴事件模擬的點擊操作,發生混亂的原因是UIScrollView滾動相關事件傳遞給了js側的Touchable,所以只要把滾動的相關事件屏蔽調就可以實現目標。

解決方法:

RCTRootView是native與js側的橋梁,所有UI觸摸事件都是通過該View傳遞給js,該View有個cancelTouches方法,用來取消當前的觸摸事件,所以,只要在scrollViewWillBeginDragging方法中調用[_rctView cancelTouches]即可。

交互與擴展

既然集成react native到本地項目中,那么必然還存在兩者之間的交互。react native核心技術是javascriptCore,交互必然也是通過它了。與WebView不同,javascriptCore是獨立存在項目中,整個react native都是通過一個單獨的jscontext建立之間的聯系,也就無法截獲WebView的請求消息進行通信。好消息是,無論舊的WebView方式還是新的javascriptCore方式,只需要封裝一下甚至無需封裝,就可以將舊的jsbridge接口移植到react native項目中。

有關jsbridge和javascriptCore可以參考之前的文章:

H5與native之間的通信

javascriptCore 詳解

如何注入到react native可以參考這篇文章:

react native之OC與js之間交互

如何注入到react native中的WebView,可以參考這篇文章:

react native之WebView中注入js接口

如何讓你的項目可以隨意更換react native服務器地址,可以參考這個工具:

react-native-debug-server-host

需要注意一點:react native的jscontext是在子線程中創建執行,所以如果你的接口中有UI的操作,需要手動指定到UI線程執行。

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

推薦閱讀更多精彩內容