[英]iOS extensions with multiple targets
在 iOS 8 中,當我們創建一個應用擴展時,我們必須決定它附加到哪個目標。 擴展將具有與目標相同的包 ID 前綴。
這是我的設置:我有 3 個目標(生產、登台、本地)和一個我不想重復 3 次的擴展目標。
為了澄清Neo Chen的答案,請編輯每個父目標的方案:
Build > Pre-actions > New Run Script Action > 從(父方案)提供構建設置。
為每個擴展粘貼這個:
#!/bin/bash
buildID=${PRODUCT_BUNDLE_IDENTIFIER}
extId="notification-service"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $buildID.$extId" "${SRCROOT}/${extId}/Info.plist"
似乎適用於第一次構建。
似乎您應該能夠使用自己的 Info.plist 復制擴展目標,但不能復制其他任何內容。
但是,當您創建一個擴展時,Xcode 會將“嵌入應用擴展”添加到應用目標的構建階段,如下所示,目前還沒有 UI 可以做到這一點。
不過,您可以為第二個目標創建擴展名,然后刪除除 .plist 之外的所有文件,並修復需要修復的內容。 這是一個分步說明:
我創建了一個運行腳本來支持這個要求
#!/bin/sh
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${SRCROOT}/ImagePush/Info.plist"
buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildVersion" "${SRCROOT}/ImagePush/Info.plist"
buildID=${PRODUCT_BUNDLE_IDENTIFIER}
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $buildID.ImagePush" "${SRCROOT}/ImagePush/Info.plist"
ImagePush 是我的擴展
添加到您需要的目標並添加確保此腳本在構建階段中的擴展設置之前運行,然后您只需要執行兩次構建操作(PS:第一次會失敗,將嘗試改進),它將支持多目標
在我的項目中,我需要構建一些不同版本的應用程序(細節不同,例如每個應用程序都標有不同的標志)。
假設有大約 10 個“應用程序”目標,我無法想象為每個主要目標添加通知內容和通知服務擴展(在這種情況下,我總共會維護 30 個目標 - 瘋狂)。
我在“嵌入應用程序擴展”階段后運行一個腳本( https://gist.github.com/damian-rzeszot/0b23ad87e5ab5d52aa15c095cbf43c59 ),它覆蓋應用程序擴展 plists 和權利、應用程序版本中的包 ID,更改配置文件並重新簽署捆綁。
Xcconfigs 是基於 Xcode 方案更改修改 plist 條目和代碼變量的好方法。
如果您想根據方案更改給定擴展的Bundle identifier
,例如:
為您的擴展創建一個 Xcconfig 文件。 我的iMessageExtension-Debug.xcconfig
有這個條目: PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).iMessageExtension
從 Xcode 文件檢查器中單擊您的項目 > 在詳細信息窗格中單擊您的項目 > 信息選項卡 > 添加配置
我創建了一個調試配置。
在您新創建的擴展配置練習中 > 選擇配置文件
創建新方案:在該新方案的運行選項卡中,您可以選擇新創建的配置。 可以為 release extra 執行相同的過程。
我們創建的 Xcconfig 選項可以直接在 iMessageExtension > Info.plist 中使用: Bundle identifier : $(PRODUCT_BUNDLE_IDENTIFIER)
如果需要在基於 xcconfig 變量的代碼中引用變量:
例如,我想根據所選的 Xcode 方案更改我的應用程序初始屏幕:
Xcconfig: INITIAL_SCREEN = tabBarHome
Plist: initialScreen : $(INITIAL_SCREEN)
Swift 代碼: var initialScreen = object(forInfoDictionaryKey: "initialScreen") as? String
var initialScreen = object(forInfoDictionaryKey: "initialScreen") as? String
2個解決方案:
XCConfig
。 請參閱此處提到的答案: https : //stackoverflow.com/a/63583849/5175709和此處。 還要在這個 SO 問題上搜索XCConfig
。 你可能會發現一些評論。 老實說,我認為XCConfig
解決方案要優雅得多。 你只是交換東西,而不是試圖以非常特定的順序覆蓋所有東西......
每個其他答案都有一部分是必要的。 通過對這篇文章的一些重要修改,我能夠把事情做好。
你需要做三件事:
注意:在嵌入之前,您無法對 appex 進行簽名。 因此,“重新簽署 appex”步驟需要在“嵌入應用程序擴展”步驟之后進行。 同樣,如果 bundleId 沒有以父應用程序的 bundleId 為前綴,則無法嵌入 appex。
最終順序應如下所示:
plutil
的 sytanx 是這樣的:
-replace keypath -type value
所以只需這樣做:
plutil -replace \
CFBundleIdentifier -string \
$PRODUCT_BUNDLE_IDENTIFIER.contentExt \
"$BUILT_PRODUCTS_DIR/contentExt.appex/Info.plist"
如果您想了解有關plutil
更多信息(請參閱此處和此處了解更多信息)。 PlistBuddy
有點老了。
注意: ContentExtension 是我擁有的目標名稱。 確保你正確使用你的
/usr/bin/codesign \
--force \
--sign $EXPANDED_CODE_SIGN_IDENTITY \
--entitlements $CONFIGURATION_TEMP_DIR/ContentExtension.build/ContentExtension.appex.xcent \
--timestamp=none \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/ContentExtension.appex"
注意: ContentExtension 是我擁有的目標名稱。 確保你正確使用你的
最終結果是這樣的:
不要忘記為每個目標重復這些步驟。 確保正確的最佳方法是將 appex 的 bundleId 設置為完全錯誤的值,然后在真實設備上測試所有目標。 如果您在 sim 上測試它,那么您將無法驗證代碼簽名是否正常工作。
FWIW 將所有 shell 轉儲到一個目錄中,然后從那里引用它們通常是個好主意。 但為了這篇文章的簡單起見,我沒有這樣做。
還要確保您看到原始要點,如果您使用它來更改所有 appexes,它會更聰明。 你只需要傳遞 appex 的名稱,然后它就會找出其余的......
您需要為每個 ID 創建多個擴展,但您可以創建動態框架並將其與每個擴展鏈接。 那么你就不需要復制你的代碼了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.