第220期 / February 5, 2016

研發新視界

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

React Native開發iOS 原生APP

作者/王琨堯

[發表日期:2016/2/5]

前言

隨著智慧型裝置的普及,裝置的應用程式需求量大增,2015年4月Facebook推出自家開發產品的程式語言React Native。React Native是基於JavaScript標準語法的程式庫,主要訴求是學一次便能在各種平台上開發(Learn once, write anywhere) APP程式,開發者可以透過React 程式庫開發組合式的使用者介面,網頁呈現資料改變時仍可重複使用的UI元件而不需重新生成,使得網頁效能上更加提升。本文章將探討透過React Native 框架開發iOS原生應用程式,框架開發者基於React Native框架開發仍然可以使用較熟悉的JavaScript語言,相對於以往需學習Objective-C或Swift才能開發iOS應用程式,進入門檻已經降低許多,對於未來APP的開發市場勢必有很大的衝擊效應。

React Native簡介

一、運作原理

一般透過JavaScript開發,讓人聯想到的就是開發網頁,而網頁能讀取網頁是因為瀏覽器中含有解讀JavaScript的核心,而在React Native中發展了自有的JavaScript核心,在React Native中如圖一分為四個階段,第一階段為接收來自JavaScript的資料,第二階段透過RTC Bridge與原生元件做溝通,第三階段利用CSS確認元件排版位置,第四階段是顯示在前端使用者介面上。


《圖一》React Native 階層示意圖


為何React Native能讓開發者透過較熟悉的JavaScript開發原生iOS,而React Native是如何在iOS上運作的呢?

React Native使用了iOS中自有的JavaScript Core,但並沒有使用原本JavaScript Core所用來介接JavaScript與Objective-C的機制,而是自己先建了一套機制,並通用於所有JavaScript Core上執行。

透過圖二可以看到從Java Script 到呼叫原生程式Objective - C必須透過兩層的界接,一層為Java Script Bridge,一層為Objective – C Bridge。當透過Java Script呼叫RTCSQLManager.query()時,指令會被放入MessageQueue並傳送至Bridge,而JavaScriptCore初始化時,包含了將模組的對應模組RemoteModuleConfig,根據模組的在Objective-C Bridge中找到相對應的模組方法,透過相對應的RCTModuleMethod以Callback的方式呼叫Objective-C Module Method。

呼叫到原生的Objective-C Module Method後,執行目標任務(在這是下達一串SQL語法)後將結果生成一個block,在block中包含了callback Id與結果回傳至Objective-C Bridge及JavaScript Bridge,最後回到JavaScript層呼叫處理Callback方法獲得結果,完成流程。


《圖二》React Native 框架運作流程圖


二、優缺點比較

React Native提供工程師多一個選擇開發APP,但其中也有些限制,這章將探討其中之優點與其限制,先來說說其中之優點:
  • Based on JavaScript + CSS

    筆者擅長於網頁語法的開發,在寫這篇文章之前完全沒碰過React Native,但在看過幾篇教學後已經可以學習到的方式改寫成自己想要的方式,想透過撰寫本篇文章之餘也寫了個範例程式,已體驗到他最大的優點,若是Objective-C,也許還要再花點時間。


  • CMD(
    如同一般開發網頁時,當完成一項頁面功能或是CSS樣式,你會很想用最快的速度看看功能或畫面是否如你所意,在React Native中就可以達到如此迅速,不必在透過一連串的重新建置(Rebuild)只為了看到你所設定的字型大小是否適合,或是功能是否正常運作,這對於開發者能省下一些時間。另外CMD+D也可以透過Chrome來debug。


  • 虛擬DOM

    此項為React Native獨有的一項優點,透過這項優點因在記憶體中運作,使得程式效率提高,React Native Framework在資料改變時也可以快速地更新呈現。


  • Cross Platform

    React Native強調的是學一次,並可以快速於任何平台開發,最主要原因是可以於不同的平台使用它自有的框架並同樣使用JavaScript開發,因此在iOS平台開發完後,以同樣的架構到Android再寫一次,也許不是100%的一樣,但也不會是從0開始,因此將可節省開發的成本。
    React Native也被與另一個APP開發框架Xamarin做比較,Xamarin使用的是C#語言,若在架構設計上傾向於將商業邏輯模組分享於不同View使用,以提高效率,架構為Module-View-Control的Xamarin會是一個不錯的選擇,話說回來若是透過React Native設計架構,相對上較自由。

三、React Native相對上的限制與未知

  • CSS樣式廣度與通用性

    React Native雖然是透過CSS來做排版,但其實它只是個很小的子集(Subset),大約支援了50種左右的屬性,再者語法與網頁的有些不一樣,若寫習慣網頁CSS在React Native上需做些寫法上的挑整。


  • 動畫效果

    網頁的動畫效果一直以來脫離不了透過JavaScript來呈現,筆者目前在React Native還沒使用到動態效果,無法認定是否能像是網頁般做出各種不同的特效,但可以確定的是iOS 原生的元件中已經有包含了動畫效果,像是Facebook的Pop就有用到,但比起JavaScript在網頁上動畫表現的程度,React Native還有一段路要走。


四、環境與開發要求

開發環境須為Mac OS X,搭配Xcode IDE建立環境來執行。在開始開發前要準備的環境如下:
  • Xcode IDE:可以從App Store中下載,需求為6.3或是更新的版。


  • Homebrew套件管理工具:它可以幫你安裝 Apple 沒有預裝但是你需要的東西。請打開終端機並鍵入以下指令。若想更新brew可以鍵入brew update。



  • React Native 使用 Node.js 來建構 JavaScript 程式,若尚未安裝則需安裝,請鍵入



  • React Native Command Line Interface:React Native CLI為輕量Node.js小程式,可用來建立新的React Native 專案,安裝後可透過React Native指令新增專案。



  • 建立新專案:在終端機內建入以下指令,透過React Native CLI會在/User/xxx/底下建立HelloWorld資料夾,內涵整包完整React Native函式庫。HelloWorld名稱可自訂。



《圖三》初始化專案


透過這五個步驟已經在完整建立一個React Native專案,接著到HelloWorld資料夾中找到HelloWorld.xcodeproj透過xcode打開,點 -R 來建置專案。若建置專案時發生Could not connect to development server的錯誤,在終端機進到專案目錄下鍵入npm start,並讓終端機畫面保持開著。


《圖四》Hello World


恭喜成功建置第一支React Native程式,而這支程式像是網站中的index.html頁面,在資料夾中你會找到一個檔案index.ios.js,這初始頁面就是來自這支Code。如下圖建立的的project名稱為AwesomeProject, 歡迎字改為Hello, Frank!


《圖五》index.ios.js初始畫面


程式開頭'use strict',為啟用Strict模式,該模式有完善的Error訊息處理機制。接著宣告變數React=require('react-native')為載入React Native模組,往後在程式中可呼叫React變數呼叫各種模組,像是在Objective-c中載入函式庫的意思。

談到這裡是否已經蠢蠢欲動想要小試身手了,建議可以先練習網路上各個教學範例,相信一定可以很快就上手,下一節將其應用改寫成“凌群電腦解決方案APP”,作為下一節將介紹說明的範例。

程式開發範例:凌群電腦解決方案搜尋APP

前一陣子公司部門主管提到應該採用易學通用的程式語言來開發出一款Mobile APP來提升業務外出推銷自家產品的效果,因此這範例是基於此目的來撰寫。畫面如圖六,範例分為三大主題,分別為「最新消息」、「解決方案」及「合作夥伴」。「最新消息」列表呈現網站最新消息中的資料,點選列表後可以看詳細內容,「解決方案」則採用凌群電腦官網中的方式,選擇領域後查看該領域中有哪些解決方案,最後合作夥伴則是採列表呈現方式。


《圖六》APP畫面


從圖七可以看到APP的架構圖,在index.iox.js中透過TabBarIOS元件將三個主體串連在一起,像是網頁上用tab分頁來做排版的概念,但不同的是它在每次點擊時會重新載入頁面。從index.ios.js設定好連結三個主題後,還需要設定預設的載入頁面,以News.js來說會透過NavigatorIOS將頁面轉到News-Lists.js內容頁,進而呈現內容。另外畫面上呈現資料來源皆為自製Web API,文章中將會提到該API位置。


《圖七》APP架構圖


了解完APP架構圖後,再來以『解決方案』為例,看看如何串起整個頁面,先來看看index.ios.js的程式碼:

在頁面轉換中須先將該JavaScript宣告為變數讓程式認得,在這頁因為要連接三個頁面,因此需做三個檔案的require宣告,如下:


接著是這一頁面會用到的元件宣告:


Main Class程式碼:



在render()中定義了TabBarIOS元件使用,在這之前別忘了在網頁最前端將該元件定義進React參數中。在Class中constructor定義TabBarIOS的初始狀態,選擇為’News’。這一頁做完後按下+R即可以在debug模式中看到網頁已經載入news.js這一個檔案了。

接著來看看solutions.js這一頁內容,這一頁算是個跳板,為的就是在接下來的頁面有導覽列,因此這頁單純就是預設NavigatorIOS的設定,因此同樣的必須將下一頁宣告好。


接著是導覽列呈現的位置,在React Native中排版採用CSS中的flex,flex是由三個屬性組合而成,依照先後順序分別是「flex-grow」、「flex-shrink」和「flex-basis」,如果 flex 只填了一個數值 ( 無單位 ),那麼預設就是以 flex-grow 的方式呈現。

flex-grow:數字,無單位,當子元素的 flex-basis 長度「小」於它自己在父元素分配到的長度,按照數字做相對應的「伸展」比例分配,預設值為 1,設為 0 的話不會進行彈性變化,不可為負值。

宣告樣式如下:


接著是Main Class宣告:


完成至此再度+R頁面已經載入至Search-picker.js。接著來看看Search-picker.js。這一頁有兩個重點。首先在頁面上方載入圖片,載入圖片目前筆者使用過兩種方式,一為將透過Xcode將圖片載入後呈現出來,另一方式則為給予圖片來源網址,此Logo是使用前者,而除了這個其他看到圖片都是透過json傳送過來的圖片來源網址呈現。

載入圖片方法打開Xcode介面後在左方找尋.xcasset。


《圖八》點選xcasset後的畫面


接著點選“+”並點選New Image Set,新增後將圖片拖曳至虛線格內,如圖九與圖十:


《圖九》點選”+”



《圖十》拖曳圖片進入虛線空格中


將圖片載入後程式碼中加上以下程式及可以將圖片呈現在畫面上。


接著這一頁另一個元件為PickerIOS。這元件主要讓使用者挑選解決方案的領域後,按下按鈕送出所選領域的id,送到Web API並回傳JSON格式的資料。使用前有兩項需要宣告:


接著宣告有哪些選項:


定義樣式:



最後是Class宣告,在Class中宣告了幾個function來完成點擊按鈕送出Query及換頁的動作:
  • onFieldSearch()

    這function是當點擊按鈕後所呼叫的,主要是抓取PickerIOS所選取的值,作為API的query值,將值與API路徑合併後呼叫_executeQuery。


  • _executeQuery()

    將組好的Query字串傳入後,透過fetch()來解析Web API 回傳的JSON格式資料,並將每一筆轉為object,並指定responseData為object集合,丟入handleResponse()中。


  • _handleResponse()

    在這個function中接收到object集合後最主要做的一件事情就是呼叫naviator.push進行傳資料到下一頁及進行跳頁動作。


處理完三個function接著來看看render中,除了圖片文字及選擇器,最重要的是有個按鈕可以點選,按鈕製作方式是如文字一樣用將文字包覆後,在用TouchableHighlight包在外層,如此該文字就能轉為可按式。


完成Search-picker.js後,透過navigator.push將object集合送至solution-list,而這一頁要做的事情就是將每個object呈現出來。在class的初始宣告中先宣告ListView,並指定資料來源為上一頁傳過來的object集合。


在這一頁的render只需要一個ListView。ListView需設定兩項參數,一為dataSource,另一項為項目的呈現renderRow,資料來源會呼叫render.Row.bind將object集合丟入


在renderRow的function中定義了object呈現的樣式,為了讓每項都能點選,在最外層也是用TouchableHighlight包覆,而這裡的image資料來源則是透過網址方式呈現。


列表這一頁的CSS樣式一樣也需要宣告一下:



完成後按下+R,即可完成該頁面。這一頁完成後當然每一個項目還需要可以點進去後看每個solution的詳細資料,因為篇幅關係最後一頁就不在文章中呈現。

結語

React Native無疑幫助想開發手機應用程式的工程師開了另一扇門,特別是專注於網頁程式開發的工程師,原本只應用在網站上的JavaScript,如今透過React Native已經可以開發出完善可用的APP,雖然React Native仍然在持續發展中,但假以時日發展成熟了,它會是很多人開發APP的首選。

參考資料