使用動態framework封裝微信SDK實踐2019-11-14

需求

對外提供一個SDK,功能是拉起微信小程序。

分析

  • 實現原理:在將要開發的SDK中,封裝微信的SDK,通過微信SDK,從而達到拉起微信小程序的目的

  • 以前項目中,接入過微信SDK,是1.8.4版本的,使用了其中的分享圖片到朋友圈的功能,比較順利,是通過CocoaPod實現的,比較省心。

  • 隨著iOS13的發布,現在的微信SDK升級到了1.8.6.1,增加了通用鏈接功能。并且通用鏈接是必選項,初始化函數增加了參數,否則就失敗。
    [WXApi registerApp:APP_ID universalLink:UNIVERSAL_LINK];
    嘗試過繞開這個通用鏈接,比如用百度的網址占位,這個函數一直返回NO

  • 說實話,通用鏈接真的很麻煩,看看微信給的介紹文章,說了一大堆,還沒把問題說清楚。并且通用鏈接只是一個用Safari瀏覽器來打開app,比較雞肋。說是增加安全性,這里也用不到。這里只是簡單拉起微信小程序就可以了,不需要回傳信息。
    關于openSDK1.8.6的更新說明

  • 提供了一個雞肋功能,導致以前的版本不能用,也不考慮兼容性,微信的SDK做得真的很差。折騰了好幾天,最終還是決定用相對簡單易用的1.8.4,避開繁瑣而沒用的通用鏈接。

  • 網上說iOSSDK一般都是靜態庫,比如微信提供的SDK就是.a形式的靜態庫。我也試著封裝了一下,發現使用起來很麻煩。比如我們提供的靜態庫叫my.a,用戶使用的時候,要把my.a和對應的頭文件my.h導入工程。由于my.a用到了微信的libWeChatSDK.a,所以用戶也要把libWeChatSDK.a和配套的頭文件導入工程。另外,libWeChatSDK.a還用到了很多系統庫,微信文檔不準確,自己查了好久的百度才link成功。這部分工作,用戶也要重復一遍,想想都麻煩。

企業微信截圖_894f5cc0-cc1d-43fc-846e-4fbab3c5a10f.png

既然這樣,封裝一層my.a又有什么意義,直接使用libWeChatSDK.a不就行了?

  • 封裝成動態framework的話,至少使用libWeChatSDK.a時遇到的麻煩事只要做一遍就好了,這樣才有封裝的意義。

結論:使用動態framework封裝WeChatSDK1.8.4實現拉起微信小程序的功能

開發動態framework

Setp1: 創建framework工程

framework的名字為工程名字,Xcode的菜單路徑為File->New->Project...,在彈出菜單中,類型選擇framework

企業微信截圖_af4ebfbd-6e81-472e-8a92-6e89493db8c4.png

工程創建完成后,會自動生成一個和framework同名的h文件,這個文件是必須的,不能刪除。

企業微信截圖_0bd3e7f9-4b21-40ab-b547-527075ec5f80.png

Setp2: 修改輸出文件

  • 默認情況下,只有與framework同名的h文件才能輸出。如果項目不大,有這么一個輸出文件就夠了。但是,只有一個h文件不是很方便,可以用一個繼承自NSObject的類代替,名字和framework同名。在頭文件中定義輸出函數。
企業微信截圖_8add109c-e94f-4402-a0bb-76e0bbe754dc.png
  • 外部可以使用的文件在Build Phases -> Headers標簽下,從Project部分移動到Public部分
企業微信截圖_1ba5ccb5-ead8-4f9f-aec7-db2f8f3b6afe.png

Step3:導入微信SDK

  • 這里選用的是WeChatSDK1.8.4,以前從微信開發者平臺下的,這個版本不需要通用鏈接,比較方便。現在網上能下的版本是WeChatSDK1.8.6.1,要求通用鏈接,用起來很麻煩,并且向前不兼容,效果很差,拋棄不用。

  • 微信SDK是靜態的.a文件,將整個文件夾通過Xcode菜單File->Add files to ...就可以了。

  • 新建一個以NSObject為基類的自定義類,這里是KJTWeiXin,通過調用微信SDK的相關函數,完成拉起微信小程序的功能。

  • 在輸出文件,這里是KJTUrlSdk.m,調用剛才的實現,完成的功能實現的導出工作。

企業微信截圖_9b730ab9-3209-4970-aaef-c56d056ae40d.png

Step4:創建調試Target

  • framework是不能直接使用的,需要一個調用者APP。這里采用Target的方式(菜單路徑File->New->Target...),名字,在framework名字后面加-Sample后綴,(這里是),類型就選最簡單的單頁面工程。
企業微信截圖_6a7f0596-a7a0-4e6c-ba8d-e03a33cbdfe3.png
  • 建立項目依賴。使用者,(這里是KJTUrlSdk-Sample),依賴framework,(這里是KJTUrlSdk)。
企業微信截圖_2e75a0b0-4e72-40b0-af4b-3d25b8ceca67.png

合并framework

生成的framework要么是真機的,要么是模擬器的,很不方便。用命令行也比較煩,用腳本的方式比較好。

  • Build Phase中的New Run Script Phase可以添加自動運行的腳本
企業微信截圖_58d63202-320f-4197-8a9d-0b55fceeb8b3.png
  • 腳本內容如下:
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
open "${DEVICE_DIR}"
open "${SRCROOT}/Products"
fi
  • 每次運行都會生成一遍,模擬器和真機至少運行一次之后,在工程根目錄下的Product文件夾下就是合并過的framework,真機和模擬都能用。
企業微信截圖_38d58813-c1a5-4394-9143-3db2260fc698.png

Step5: Demo工程

  • 創建一個獨立的工程,使用自己開發的framework。這個工程要和前面的開發工程完全獨立。名字可以加-Demo后綴,(這里是KJRUrlSdk-Demo

  • 通過菜單Flie->Add files to ... 將合并過的framework添加進來。

注意:如果要提交蘋果市場,只能用真機版本的framework,否則會出錯。

  • 在General標簽下,將framework的載入格式改為Embed&Sign,否則會奔潰。
企業微信截圖_318404b0-b634-446d-9024-3b7bfcf20e36.png

如果不改,崩潰信息一般如下:
dyld: Library not loaded: @rpath/KJTUrlSdk.framework/KJTUrlSdk
Referenced from: /var/mobile/Containers/Bundle/Application/CFEEFAD2-1BF3-4D29-967B-42CAAB7C4811/KJTUrlSdk-Demo.app/KJTUrlSdk-Demo
Reason: image not found

最后的樣子:經過以上各步驟,最后的文件結構樣子大致如下

企業微信截圖_46c1c67c-ca66-408c-8b50-0b37fb30f330.png

微信SDK依賴系統庫

  • 微信 WeChatSDK1.8.4依賴如下系統庫
企業微信截圖_071c4e89-edfd-42bb-b371-fda4f64fc562.png
  • 如果不添加這些系統庫,會出現鏈接錯誤,并且這些問題,微信的開發文檔并沒有完全說清楚。只能百度,一個個試過去,比較麻煩。
    導入微信支付報錯解決

  • 使用動態framework包含一個靜態.a的好處是上面那些依賴可以在framework內部處理掉,最終使用者,這里是KJTUrlSdk-Demo,就不需要再考慮這些麻煩事了。

注冊函數導致崩潰。

  • 由于是MTA庫中的剪貼板和其他程序競爭,導致崩潰。只要不打開MTA就好了。
    WXApi registerApp:@"xxx" enableMTA:NO];

[__NSArrayM enqueue:]: unrecognized selector sent to instance

  • WeChatSDK1.8.5之后的版本解決了這個問題。
企業微信截圖_9af8874b-d246-40ce-a716-20915a36e158.png

檢查微信是否安裝函數不可用

這是因為微信SDK使用[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin://"]]方式來檢查是否安裝微信。iOS9之后,要在Plist中加白名單才可以用。不然這個函數始終返回NO

企業微信截圖_f9a9e6c0-4a8a-4a42-bcd9-bb8627a8c788.png

[WXApi isWXAppInstalled]

應用BundleID信息校驗不通過

  • 如果使用者APPbundle ID,(這里是KJTUrlSdk-DemoKJTUrlSdk-Sample),和微信后臺配置的bundle ID不一致,就會彈這個信息框,小程序跳轉也有異常。但是,微信API函數執行還是成功的。
企業微信截圖_c5762cab-aeca-4548-a837-7a65b9c81af1.png
企業微信截圖_4af8688e-f225-4038-b029-e6f06d434355.png

framework的版本號

  • framework工程創建的時候,會自動給出兩個關于版本的全局變量,一個是double型的,一個是char數組
企業微信截圖_6f17cd00-b1df-47c5-bd55-4e439f73c8d2.png
  • 這兩個變量對應的是Target->General下的Build,并不是通常理解的Version
企業微信截圖_662decb7-c7c7-4fd6-b585-58bb9fc730d2.png
  • double型的數字只能顯示兩位,比如設置1.2.3.4,顯示1.200000;字符型的能顯示全,不過會加上很多前綴。比如Build配置為1.2.3.4,通過NSLog輸出:
    NSLog(@"數字版本號:%f", KJTUrlSdkVersionNumber); // 數字版本號:1.200000
    NSLog(@"字符數組版本號:%s", KJTUrlSdkVersionString); // 字符數組版本號:@(#)PROGRAM:KJTUrlSdk  PROJECT:KJTUrlSdk-1.2.3.4

如何生成Release模式的framework?

  • 一般的scheme,都是Run的時候Debug,Archive的時候Release。這個設定對于可執行文件是可行的,但是對于framework就不合適了。因為framework無法單獨執行,沒法Archive

  • 可以將frameworkRun改為Release。就算這樣,用斷點調試,也是可以停住的,不影響調試效果。可以這樣說,Debug模式對于framework來說是沒有意義的,統一使用Release就好了。

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

推薦閱讀更多精彩內容