1. 程式人生 > IOS開發 >iOS開發:整合的SDK不支援模擬器除錯怎麼辦?

iOS開發:整合的SDK不支援模擬器除錯怎麼辦?

作者:GSC

  最近在專案的開發中遇到了一個問題。使用者反映在iPhone Xs Max上一些介面顯示異常。但是手頭沒有這個手機,而且自從集成了螢石雲的SDK以後,專案無法在模擬器上除錯。現在再申請購置一部XS Max手機也來不及了,而且總不能一遇到手頭沒有的裝置就申請新手機吧。於是就需要考慮如何讓這種集成了不支援模擬器的SDK如何也能在模擬器上執行,從而解決這類專案中遇到的個別機型差異造成的BUG。

一、什麼情況下出現這種問題

  剛才說了,出現在這種問題是集成了第三方的SDK,該SDK不支援模擬器執行。其實,再問題具體一點,是因為這類SDK不支援在x86下編譯的話,則不能在模擬器上除錯執行。

二、解決這種問題的思路。

  其實,解決這類問題的方法就是四個字:條件編譯。利用條件編譯,在模擬器環境下不對不支援x86的SDK進行編譯即可。

  對於有些SDK提供了兩套版本,一套Release環境,一套Debug環境。Debug環境支援在模擬器進行,對於這類SDK,則可以通過替換SDK的framework的方式來解決模擬器除錯問題。比如阿里雲短視訊SDK,七牛視訊播放SDK等等。

三、具體解決問題的方法。

  我們要設定一個預編譯巨集,來處理條件編譯,比如設定一個預編譯巨集,名字叫EZDISABLE。在TargetBuild Settings選項卡下面,我們找到Preprocessor Macros

項,雙擊後增加一項:EZDISABLE=1。可以只在Debug 或者只在Release加入該巨集,具體依據你自己的需求而定。這裡我都加入了。

  下面,就是將用到不支援x86的SDK的呼叫,通過EZDISABLE 巨集“隔離”開。在我這個專案中,需要把螢石雲的SDK“隔離”。

// 如果沒有定義EZDISABLE巨集,則編譯以下內容,否則不編譯
#ifndef EZDISABLE
#import <EZOpenSDKFramework/EZOpenSDKFramework.h>
#endif
......
......

- (void)setupEZ{
// 如果沒有定義EZDISABLE巨集,否則不編譯
#ifndef EZDISABLE
   [EZOpenSDK initLibWithAppKey:@"xxxxxx"];
#endif
}
複製程式碼

  程式碼可能分散的比較多,需要耐心的一個個把他給去掉。

  上面還說了,有些SDK分ReleaseDebug兩個版本,Debug支援模擬器編譯。對於這類,如果你的SDK是通過手工新增的方式來整合的話,那你就手工一個個一個把SDK給替換了,如果你用的是cocoaPods的話,那一般只需要將**Podfile的引用稍作修改既可以。我這個用的是cocoaPods來整合的七牛視訊播放SDK。我將Podfile檔案修改成下面的即可:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios,'8.0'
inhibit_all_warnings!
target 'BBTSer' do
  ...
  ...
  pod "PLPlayerKit",:podspec => 'https://raw.githubusercontent.com/pili-engineering/PLPlayerKit/master/PLPlayerKit-Universal.podspec'	#七牛官方提供的支援模擬器的版本,在官方網站上可以查到
end
複製程式碼

  有時候,我們為了方便程式碼的複用,做了很多的私有Pod子庫提供給主專案整合。如果在這些私有庫中引用了類似七牛這種SDK該怎麼辦?其實我們根據cocoaPods的規則,完全可以不用考慮子庫,直接在主工程的Podfile檔案將SDK的引用改了就行。cocoaPods會自動處理這類依賴,非常方便。

四、問題優化。

  在上面,已經基本上解決了如何在模擬器上編譯的問題。但是不太方便,我們總不能每次切換真機與模擬器的時候,都去修改一下預編譯巨集和Podfile檔案吧?

  具體該怎麼進行優化可以讓我們方便的切換除錯環境呢?

  對於預編譯巨集的設定,我們可以通過再設定一個Target的方式來處理,我們將工程的Target複製一個,比如原工程Target名字為:BBTSer。複製的一個改名為:BBTSer Simulator。我們只在BBTSer SimulatorBuild Settings選項卡中的Preprocessor Macros增加預編譯巨集EZDISABLE=1。原來的老Target不變。如果用cocoaPods的話,在增加了一個新的Target後要相應的修改一下Podfile檔案來增加對這個Target的支援。這樣,就可以通過切換Targe的方式來處理真機與模擬器的除錯切換。

  再說下Podfile檔案的優化。上面講了,對於七牛的SDK官方支援了在模擬器除錯,但是是不同的pod庫地址。需要進行切換。那麼我們如何能夠使cocoaPod能夠以一種相對自動的方式來處理這種切換呢?這需要我們更加的瞭解Podfile的語法才行。首先,在上面我們建立了兩個Target。所以Podfile檔案要同時處理兩個Target的整合。然後,對於不同的Target有可能要整合不同的七牛SDK地址,如何在pod install的時候來處理這種不同?

  對於第一個問題其實很簡單,百度一下很多方式,這裡不在敘述。對於第二個問題需要說一下。在Podfile中,如果兩個或者多個Target引用了相同的pod庫,但是原始檔地址不一樣的話,是會報錯的。那麼我們就需要增加一個開關來處理一下,如果開關開啟,則引入正常地址,如果開關關閉則引入另外一個地址。我們知道,Podfile檔案的語法其實跟Ruby差不多。所以,我們可以增加一個變數release,然後通過判斷release變數是false還是true來引入不同的源地址。這樣,我們的Podfile檔案就變成了如下行使。

source 'https://github.com/CocoaPods/Specs.git'
platform :ios,'8.0'
inhibit_all_warnings!
#開關變數
release=false
# abstract_target:抽象target。內部包含兩個Target:BBTSer和BBTSer Simulator。這兩個Targe繼承這個抽象target。抽象target的名字可以隨意定義,這裡我定義成BBT
abstract_target 'BBT' do	
  ...
  ...
  if release then
    target 'BBTSer' do
      pod "PLPlayerKit"
    end
  else
    target 'BBTSer Simulator' do
      pod "PLPlayerKit",:podspec => 'https://raw.githubusercontent.com/pili-engineering/PLPlayerKit/master/PLPlayerKit-Universal.podspec'
    end
  end
end
複製程式碼

到了這裡,我們在每次切換模擬器和真機的時候,只要把release的狀態改一下就可以了,真機改成true,模擬器改成false。然後在pod install或者pod update。你可能會說,這樣也不好。每次還要改Podfile檔案。那麼好,我再加一個shell指令碼,來幫著我們處理這個改動,不要每次都改Podfile檔案了,省的不小心改錯了。shell檔案起名為podinstall.sh。內容如下:

#!/bin/bash
file="Podfile"
if [ ! -f "$file" ]; then
  echo '沒有找到Podfile檔案'
  exit
fi

if [ ! -n "$1" ] ;then
    echo "請輸入引數。真機除錯以及釋出到AppStore請輸入release,模擬器除錯輸入debug"
    exit
fi

MODE=$1
if [ "$MODE" != "release" ] && [ "$MODE" != "debug" ];then
    echo "請輸入正確的引數。真機除錯以及釋出到AppStore請輸入release,模擬器除錯輸入debug"
    exit
fi
echo "當前整合環境:$MODE"

podmodel="release=false"
if [ "$MODE" == "release" ];then
    podmodel="release=true"
fi
echo $podmodel
# sed -i "s/release=true/$podmodel/g" 
# sed -i '' '/release=true/$podmodel/g' $file
sed -i '' "s#release=true#$podmodel#g" $file
sed -i '' "s#release=false#$podmodel#g" $file

#更新pod配置
echo "********************************************"
echo "*      配置完畢,開始Pod整合        *"
echo "********************************************"
pod install
複製程式碼

每次pod install的時候,用這個shell來代替。將它和Podfile檔案放到一起。真機pod呼叫./podinstall.sh release。模擬器pod呼叫./podinstall.sh debug。怎麼樣,是不是方便多了?