如何将应用程序扩展添加到私有 Pod 中?

Posted

技术标签:

【中文标题】如何将应用程序扩展添加到私有 Pod 中?【英文标题】:How can I add an app-extension into a private pod? 【发布时间】:2020-02-25 19:37:58 【问题描述】:

我想知道是否可以在私有 pod 中创建应用扩展(例如 NotificationContentExtension)?我不认为这是可能的,因为:

在我的私人 pod 项目中,当我尝试添加 ios 扩展时,它会尝试将其与 bundleIdentifier 相关联。这至少会导致两个问题,甚至更多:

在创建 pod 时,我不知道主应用的 bundleID 应用扩展基本上与项目相关联。但我不认为pod install 会为我的项目添加一个新目标

我的解决方法是在我的 pod 项目中有一个子 pod,将其命名为 ContentExtensionHandler,然后在我的应用扩展中导入该子 pod,替换其中的视图并将事件传递给应用扩展,但我不认为这是干净的方法。

我看到了一些关于 SO 的问题,但它们主要是关于如何将 pod 添加到您的应用程序扩展中。我想做完全相反的事情。将应用程序扩展添加到我的 pod 中,然后在我执行 pod install 时使应用程序扩展可用。

有没有人知道对此有更好的解决方案,或者 Apple 或 Cocoapods 对此有什么具体建议?

【问题讨论】:

我的理解是你不能。你也不应该。宿主应用程序本身应该知道它的所有目标。您应该做的是拦截来自主机应用程序的通知,然后根据您拥有的任何参数,将其传递到您的 pod 的 serviceExtensionHandler 【参考方案1】:

我的理解是你不能。你也不应该。父应用程序本身应该知道它的所有目标。并且鉴于每个 App Extension 的 bundleId 都以其父应用程序的 bundleId 为前缀,因此需要大量构建工具才能从 pod 本身获取bundleIdplist、权利、配置文件、代码签名.

你应该做的是拦截来自宿主应用程序的通知,然后根据你拥有的任何参数,将它传递给你的 pod 的 serviceExtensionHandler。

但是,如果您不希望在应用程序中有多个目标而头疼,那么您可以在父应用程序中拥有一个目标并使用一些脚本来更改所有 bundleIdplist、权利、配置文件,代码签名

我在网上找到的最佳答案是由damian-rzeszot从this gist写的,最初是从here写和引用的:

alias plistbuddy=/usr/libexec/PlistBuddy
alias codesign=/usr/bin/codesign


#
# Bundle identifier
#

set_plist_bundle_identifier() 
  local bundle_identifier="$1"
  local plist_file="$2"

  plistbuddy \
    -c "set :CFBundleIdentifier $bundle_identifier" \
    "$plist_file"


set_appex_bundle_identifier() 
  local appex_target_name="$1"
  local bundle_identifier_suffix="$2"

  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="$1"
  local plist_file="$2"

  plistbuddy \
    -c "set :CFBundleShortVersionString $bundle_version" \
    "$plist_file"


get_plsit_bundle_version() 
  local plist_file="$1"

  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="$1"
  local bundle_version="$2"

  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="$1"
  local plist_file="$2"

  plistbuddy \
    -c "set :CFBundleVersion $bundle_build" \
    "$plist_file"


get_plist_bundle_build() 
  local plist_file="$1"

  plistbuddy \
    -c "Print :CFBundleVersion" \
    "$plist_file"


set_appex_bundle_build() 
  local appex_target_name="$1"
  local bundle_version="$2"

  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="$1"
  local bundle_identifier_suffix="$2"
  local output_file="$3"

  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="$1"
  local provision_source="$2"

  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="$1"
  local entitlements_file="$2"

  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 中?的主要内容,如果未能解决你的问题,请参考以下文章

将 pod 添加到 Today 扩展会强制生成通用存档

项目添加pod管理以及创建本地私有库

将 Firebase 添加到 Pod 项目

如何为分叉和修改的公共 pod 添加预期版本?

如何在主应用程序目标中使用单元测试用例(作为 test_spec 添加到开发 pod)?

远程私有库的创建 pod