簡體   English   中英

具有多個目標的 iOS 擴展

[英]iOS extensions with multiple targets

在 iOS 8 中,當我們創建一個應用擴展時,我們必須決定它附加到哪個目標。 擴展將具有與目標相同的包 ID 前綴。

  1. 之后有沒有辦法改變目標?
  2. 如果我的項目包含 2 個(或更多)目標(例如一個用於調試/模擬器,一個用於生產/設備),使用擴展的最佳方式是什么? 我是否需要創建另一個擴展並復制代碼(為兩個目標保留相同的代碼非常麻煩)?

要與其他目標共享一個小部件,您只需在General配置選項卡中為每個父目標添加 widget.appex 目標到Embedded Binaries

在此處輸入圖片說明

然后你會在Build Phases自動獲得Embed App Extensions區域

在此處輸入圖片說明

這是我的設置:我有 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 之外的所有文件,並修復需要修復的內容。 這是一個分步說明:

  • 為“目標 1”創建“擴展 1”
  • 為“目標 2”創建“擴展 2”
  • 刪除為“擴展 2”創建的所有文件,除了其 Info.plist
  • 使“擴展 2”目標的“構建階段”與“擴展 1”的構建階段相同。 通常將必要的 .m 文件添加到“編譯源”階段,並將資源添加到“復制捆綁資源”階段

我創建了一個運行腳本來支持這個要求

#!/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 ,例如:

  1. 為您的擴展創建一個 Xcconfig 文件。 我的iMessageExtension-Debug.xcconfig有這個條目: PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).iMessageExtension

  2. 從 Xcode 文件檢查器中單擊您的項目 > 在詳細信息窗格中單擊您的項目 > 信息選項卡 > 添加配置

  3. 我創建了一個調試配置。

  4. 在您新創建的擴展配置練習中 > 選擇配置文件

  5. 創建新方案:在該新方案的運行選項卡中,您可以選擇新創建的配置。 可以為 release extra 執行相同的過程。

  6. 我們創建的 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 的 bundleId(應用擴展)
  • 更改捆綁包后重新簽署 appex。 當應用程序在模擬器上正確運行時,如果沒有這一步,它就無法在真實設備上運行。
  • 設置適當的配置文件。 (從這個答案中排除,因為我還不知道該怎么做)

注意:在嵌入之前,您無法對 appex 進行簽名。 因此,“重新簽署 appex”步驟需要在“嵌入應用程序擴展”步驟之后進行。 同樣,如果 bundleId 沒有以父應用程序的 bundleId 為前綴,則無法嵌入 appex。

最終順序應如下所示:

在此處輸入圖片說明

更改 appex 的 bundleId

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM