如何将应用程序扩展添加到私有 pod 中?
How can I add an app-extension into a private pod?
我想弄清楚是否可以在私有 pod 中创建应用程序扩展(例如 NotificationContentExtension)?我不认为这是可能的,因为:
在我的私人 pod 项目中,当我尝试添加 iOS 扩展时,它试图将其与 bundleIdentifier 相关联。这至少会导致两个问题,甚至可能会导致更多问题:
- 我在创建 pod 时不知道主应用程序的 bundleID
- 应用扩展基本上与项目相关联。但我不认为
pod install
只会向我的项目添加一个新目标
我的解决方法是在我的 pod 项目中有一个子 pod,将其命名为 ContentExtensionHandler 并将该子 pod 导入我的应用程序扩展中,替换其中的视图并将事件传递给应用程序扩展,但我不认为这是一个干净的方法。
我在 SO 上看到了一些问题,但它们主要是关于如何将 pods 添加到您的应用程序扩展。我想做完全相反的事情。将应用程序扩展添加到我的广告连播中,然后在我执行 pod install
时让应用程序扩展可用。
有谁知道对此有更好的解决方案,或者 Apple 或 Cocoapods 对此有具体建议吗?
我的理解是你不能。你也不应该。父应用程序本身应该知道它的所有目标。鉴于每个 App Extension 的 bundleId 都以其父应用程序的 bundleId 为前缀,它需要大量的构建工具才能获得 bundleId
、plist
、权利、配置文件、代码签名权利来自 pod 本身。
您应该做的是拦截来自主机应用程序的通知,然后根据您拥有的任何参数,将其传递到您的 pod 的 serviceExtensionHandler。
然而,如果您不希望在应用程序中拥有多个目标而头疼,那么您可以在父应用程序中拥有一个目标并使用一些脚本来更改所有 bundleId
、plist
、权利、配置文件、代码签名
我在网上找到的最佳答案是damian-rzeszot from this gist originally written and referenced from here写的:
alias plistbuddy=/usr/libexec/PlistBuddy
alias codesign=/usr/bin/codesign
#
# Bundle identifier
#
set_plist_bundle_identifier() {
local bundle_identifier=""
local plist_file=""
plistbuddy \
-c "set :CFBundleIdentifier $bundle_identifier" \
"$plist_file"
}
set_appex_bundle_identifier() {
local appex_target_name=""
local bundle_identifier_suffix=""
local bundle_identifier="$PRODUCT_BUNDLE_IDENTIFIER.$bundle_identifier_suffix"
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_identifier "$bundle_identifier" "$plist_file"
}
#
# Bundle version
#
set_plist_bundle_version() {
local bundle_version=""
local plist_file=""
plistbuddy \
-c "set :CFBundleShortVersionString $bundle_version" \
"$plist_file"
}
get_plsit_bundle_version() {
local plist_file=""
plistbuddy \
-c "Print :CFBundleShortVersionString" \
"$plist_file"
}
get_app_bundle_version() {
local plist_file="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
get_plsit_bundle_version "$plist_file"
}
set_appex_bundle_version() {
local appex_target_name=""
local bundle_version=""
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_version "$bundle_version" "$plist_file"
}
#
# Bundle build
#
set_plist_bundle_build() {
local bundle_build=""
local plist_file=""
plistbuddy \
-c "set :CFBundleVersion $bundle_build" \
"$plist_file"
}
get_plist_bundle_build() {
local plist_file=""
plistbuddy \
-c "Print :CFBundleVersion" \
"$plist_file"
}
set_appex_bundle_build() {
local appex_target_name=""
local bundle_version=""
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_build "$bundle_version" "$plist_file"
}
get_app_bundle_build() {
local plist_file="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
get_plist_bundle_build "$plist_file"
}
#
# Code signing
#
prepare_entitlements_file() {
local appex_target_name=""
local bundle_identifier_suffix=""
local output_file=""
local original_entitlements="$CONFIGURATION_TEMP_DIR/$appex_target_name.build/$appex_target_name.appex.xcent"
local bundle_identifier="$DEVELOPMENT_TEAM.$PRODUCT_BUNDLE_IDENTIFIER.$bundle_identifier_suffix"
cp "$original_entitlements" "$output_file"
if [[ $CONFIGURATION == "Release" ]]
then
plistbuddy \
-c "set :application-identifier $bundle_identifier" \
"$output_file"
plistbuddy \
-c "set :keychain-access-groups:0 $bundle_identifier" \
"$output_file"
fi
}
copy_provisioning_profile() {
local appex_target_name=""
local provision_source=""
local provision_destination="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/$EMBEDDED_PROFILE_NAME"
cp "$provision_source" "$provision_destination"
}
resign_appex() {
local appex_target_name=""
local entitlements_file=""
codesign \
--force \
--sign "$EXPANDED_CODE_SIGN_IDENTITY" \
--entitlements "$entitlements_file" \
--timestamp=none \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex"
}
#
#
#
#
#
set_appex_bundle_identifier \
"NotificationService" \
"notification-service"
set_appex_bundle_version \
"NotificationService" \
`get_app_bundle_version`
set_appex_bundle_build \
"NotificationService" \
`get_app_bundle_build`
# Be careful if using `keychain-access-groups` entitlement
prepare_entitlements_file \
"NotificationService" \
"notification-service" \
"$DERIVED_SOURCES_DIR/NotificationService-Entitlements.plist"
copy_provisioning_profile \
"NotificationService" \
"$SOURCE_ROOT/../.github/appstore/$TARGET_NAME/profiles/notification-service.mobileprovision"
resign_appex \
"NotificationService" \
"$DERIVED_SOURCES_DIR/NotificationService-Entitlements.plist"
我想弄清楚是否可以在私有 pod 中创建应用程序扩展(例如 NotificationContentExtension)?我不认为这是可能的,因为:
在我的私人 pod 项目中,当我尝试添加 iOS 扩展时,它试图将其与 bundleIdentifier 相关联。这至少会导致两个问题,甚至可能会导致更多问题:
- 我在创建 pod 时不知道主应用程序的 bundleID
- 应用扩展基本上与项目相关联。但我不认为
pod install
只会向我的项目添加一个新目标
我的解决方法是在我的 pod 项目中有一个子 pod,将其命名为 ContentExtensionHandler 并将该子 pod 导入我的应用程序扩展中,替换其中的视图并将事件传递给应用程序扩展,但我不认为这是一个干净的方法。
我在 SO 上看到了一些问题,但它们主要是关于如何将 pods 添加到您的应用程序扩展。我想做完全相反的事情。将应用程序扩展添加到我的广告连播中,然后在我执行 pod install
时让应用程序扩展可用。
有谁知道对此有更好的解决方案,或者 Apple 或 Cocoapods 对此有具体建议吗?
我的理解是你不能。你也不应该。父应用程序本身应该知道它的所有目标。鉴于每个 App Extension 的 bundleId 都以其父应用程序的 bundleId 为前缀,它需要大量的构建工具才能获得 bundleId
、plist
、权利、配置文件、代码签名权利来自 pod 本身。
您应该做的是拦截来自主机应用程序的通知,然后根据您拥有的任何参数,将其传递到您的 pod 的 serviceExtensionHandler。
然而,如果您不希望在应用程序中拥有多个目标而头疼,那么您可以在父应用程序中拥有一个目标并使用一些脚本来更改所有 bundleId
、plist
、权利、配置文件、代码签名
我在网上找到的最佳答案是damian-rzeszot from this gist originally written and referenced from here写的:
alias plistbuddy=/usr/libexec/PlistBuddy
alias codesign=/usr/bin/codesign
#
# Bundle identifier
#
set_plist_bundle_identifier() {
local bundle_identifier=""
local plist_file=""
plistbuddy \
-c "set :CFBundleIdentifier $bundle_identifier" \
"$plist_file"
}
set_appex_bundle_identifier() {
local appex_target_name=""
local bundle_identifier_suffix=""
local bundle_identifier="$PRODUCT_BUNDLE_IDENTIFIER.$bundle_identifier_suffix"
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_identifier "$bundle_identifier" "$plist_file"
}
#
# Bundle version
#
set_plist_bundle_version() {
local bundle_version=""
local plist_file=""
plistbuddy \
-c "set :CFBundleShortVersionString $bundle_version" \
"$plist_file"
}
get_plsit_bundle_version() {
local plist_file=""
plistbuddy \
-c "Print :CFBundleShortVersionString" \
"$plist_file"
}
get_app_bundle_version() {
local plist_file="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
get_plsit_bundle_version "$plist_file"
}
set_appex_bundle_version() {
local appex_target_name=""
local bundle_version=""
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_version "$bundle_version" "$plist_file"
}
#
# Bundle build
#
set_plist_bundle_build() {
local bundle_build=""
local plist_file=""
plistbuddy \
-c "set :CFBundleVersion $bundle_build" \
"$plist_file"
}
get_plist_bundle_build() {
local plist_file=""
plistbuddy \
-c "Print :CFBundleVersion" \
"$plist_file"
}
set_appex_bundle_build() {
local appex_target_name=""
local bundle_version=""
local plist_file="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/Info.plist"
set_plist_bundle_build "$bundle_version" "$plist_file"
}
get_app_bundle_build() {
local plist_file="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
get_plist_bundle_build "$plist_file"
}
#
# Code signing
#
prepare_entitlements_file() {
local appex_target_name=""
local bundle_identifier_suffix=""
local output_file=""
local original_entitlements="$CONFIGURATION_TEMP_DIR/$appex_target_name.build/$appex_target_name.appex.xcent"
local bundle_identifier="$DEVELOPMENT_TEAM.$PRODUCT_BUNDLE_IDENTIFIER.$bundle_identifier_suffix"
cp "$original_entitlements" "$output_file"
if [[ $CONFIGURATION == "Release" ]]
then
plistbuddy \
-c "set :application-identifier $bundle_identifier" \
"$output_file"
plistbuddy \
-c "set :keychain-access-groups:0 $bundle_identifier" \
"$output_file"
fi
}
copy_provisioning_profile() {
local appex_target_name=""
local provision_source=""
local provision_destination="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex/$EMBEDDED_PROFILE_NAME"
cp "$provision_source" "$provision_destination"
}
resign_appex() {
local appex_target_name=""
local entitlements_file=""
codesign \
--force \
--sign "$EXPANDED_CODE_SIGN_IDENTITY" \
--entitlements "$entitlements_file" \
--timestamp=none \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/$BUNDLE_PLUGINS_FOLDER_PATH/$appex_target_name.appex"
}
#
#
#
#
#
set_appex_bundle_identifier \
"NotificationService" \
"notification-service"
set_appex_bundle_version \
"NotificationService" \
`get_app_bundle_version`
set_appex_bundle_build \
"NotificationService" \
`get_app_bundle_build`
# Be careful if using `keychain-access-groups` entitlement
prepare_entitlements_file \
"NotificationService" \
"notification-service" \
"$DERIVED_SOURCES_DIR/NotificationService-Entitlements.plist"
copy_provisioning_profile \
"NotificationService" \
"$SOURCE_ROOT/../.github/appstore/$TARGET_NAME/profiles/notification-service.mobileprovision"
resign_appex \
"NotificationService" \
"$DERIVED_SOURCES_DIR/NotificationService-Entitlements.plist"