react-native.png

在上一篇 React Native 初心者攻略 中有說明如何在實體 iPhone 上開發

透過 AppDelegate.m 這個檔案我們可以將 localhost 手動更改成電腦 ip 來達到實機測試的目的

但是這樣的開發方式有幾個缺點

  1. 需要經常手動去做更改,尤其當你是使用筆電,甚至是和其他人共同開發的狀況,就會常常在 merge 時衝突,除非團隊都使用 localhost 以 simulator 進行開發
  2. 沒辦法在實體機器上 Debug in Chrome

在開發一段時間後,實在受不了,好在找到了自動設定的方法

透過 shell script 抓取電腦的 IP 後,寫入到專案

設置方法

抓取電腦 IP

我們需要先寫出能夠抓取電腦 IP 的指令

網路上大多使用這個指令,可以先填到 terminal 執行看看,確認 IP 是否正確

ifconfig | grep inet\ | tail -1 | cut -d " " -f 2

但是因為我們專案後端 server 有使用到 docker ,使用上面 command 抓到的是錯誤的 IP

所以我需要改成這樣

ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1

OK 我們現在能夠拿到正確的 IP 了

Add Run Script

再來我們需要設定在專案執行時執行一段 shell script 去抓取 IP 寫入到專案中

照著圖中藍色 focus 的地方找到 Build Phases

{% asset_img addScript.png %}

新增一個 Run Script 後的畫面

{% asset_img editScript.png %}

接下來就是填入主角 script 了

下面的 script 會在專案的 INFOPLIST 裡新增一個 SERVER_IP 的欄位,並把 IP 寫入

1
2
3
4
5
6
INFOPLIST="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
echo "writing to $INFOPLIST"
PLISTCMD="Add :SERVER_IP string $(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1)"
echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" || true
PLISTCMD="Set :SERVER_IP $(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1)"
echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" || true

填好之後會像這樣

{% asset_img addedScript.png %}

AppDelegate.m 讀取 SERVER_IP

打開 AppDelegate.m

將原本

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

替換成能夠動態改變 SERVER_IP 的 code

1
2
3
4
NSString *serverIP = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SERVER_IP"];
NSString *jsCodeUrlString = [NSString stringWithFormat:@"http://%@:8081/index.ios.bundle?platform=ios&dev=true", serverIP];
NSString *jsBundleUrlString = [jsCodeUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
jsCodeLocation = [NSURL URLWithString:jsBundleUrlString];
{% asset_img AppDelegate.png %}

這時候你可以測試看看 simulator 和 real device 上是不是都能正常運作,可以的話就成功囉!

Debug in Chrome on Real Device

找到 RCTWebSocketExecutor.m 的 setUp

RCTWebSocketExecutor.png

將這行

1
NSString *URLString = [NSString stringWithFormat:@"http://localhost:%zd/debugger-proxy?role=client", port];

替換成

1
2
NSString *serverIP = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SERVER_IP"];
NSString *URLString = [NSString stringWithFormat:@"http://%@:%zd/debugger-proxy?role=client", serverIP, port];

這邊一樣是將 localhost 改成 SERVER_IP

實體裝置就能透過 wifi 在電腦的 chrome 上進行 debug 了,趕快試試看!

Reference

http://moduscreate.com/automated-ip-configuration-for-react-native-development/