在iOS 8中,当我们创建一个新的扩展时,我们必须决定它所附加的目标。扩展名将具有与目标相同的捆绑包ID前缀。
答案 0 :(得分:25)
要在很多目标中共享一个小部件,应该只添加widget.appex目标
Embedded Binaries
配置选项卡中每个父目标的General
然后,您将自动Embed App Extensions
Build Phases
区域
答案 1 :(得分:9)
您似乎应该能够使用自己的Info.plist复制Extension目标,但不能复制任何其他内容。
但是,当您创建扩展时,Xcode会将“嵌入应用程序扩展”添加到应用程序目标的构建阶段,如下所示,并且还没有UI可以执行此操作。
但是,您可以为第二个目标创建扩展,然后删除除.plist之外的所有文件,并修复需要修复的内容。这是一步一步:
答案 2 :(得分:8)
这是我的设置:我有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"
似乎可以在首次构建时使用。
答案 3 :(得分:4)
我已创建一个运行脚本来支持此要求
#!/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是我的扩展
向目标添加您需要的那个并添加以确保此脚本在Build Phases中的扩展设置之前运行,然后您只需要执行两次构建操作(PS:第一次它将失败,将尝试改进)它将支持多个目标
答案 4 :(得分:3)
在我的项目中,我需要构建一些不同版本的应用程序(细节有所不同,例如,每个应用程序都贴有不同的徽标)。
让我们说大约有10个“应用”目标,我无法想象每个主要目标都会添加Notification Content和Notification Service扩展(在这种情况下,我总共将维护30个目标-疯狂)。
我在“嵌入应用扩展”阶段之后运行脚本(https://gist.github.com/damian-rzeszot/0b23ad87e5ab5d52aa15c095cbf43c59), 会覆盖应用扩展插件和权利,应用版本中的捆绑包ID,更改设置配置文件并重新签名捆绑包。
答案 5 :(得分:1)
您需要为每个ID创建多个扩展,但您可以创建动态框架并将其与每个扩展名链接。然后,您不需要复制代码。
答案 6 :(得分:0)
Xcconfigs是修改plist条目和基于Xcode方案更改的代码变量的好方法。
如果要基于方案更改Bundle identifier
(例如,给定扩展名)
为扩展名创建Xcconfig文件。我的iMessageExtension-Debug.xcconfig
具有以下条目:
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).iMessageExtension
从Xcode文件检查器中单击您的项目>在详细信息窗格中,单击您的项目>信息选项卡>添加配置
我创建了一个调试配置。
在新创建的配置中,钻至扩展名>选择配置文件
创建新方案:在该新方案的运行选项卡中,您可以选择新创建的配置。可以执行相同的过程以释放额外的内容。
我们创建的Xcconfig选项可以直接在iMessageExtension> Info.plist内部使用:
Bundle identifier : $(PRODUCT_BUNDLE_IDENTIFIER)
如果您需要基于xcconfig变量在代码中引用一个变量:
例如,我想根据所选的Xcode方案更改应用程序初始屏幕:
Xcconfig:
INITIAL_SCREEN = tabBarHome
列表:
initialScreen : $(INITIAL_SCREEN)
快捷代码:
var initialScreen = object(forInfoDictionaryKey: "initialScreen") as? String
答案 7 :(得分:0)
其他所有答案都有其必要之处。通过对此post进行一些重要的修改,我可以使事情变得正确。
您需要做三件事:
注意:您无法在appex嵌入之前对其进行签名。因此,“重新签名appex”步骤需要在“嵌入式应用程序扩展”步骤之后进行。同样,如果bundleId不以父应用程序的bundleId为前缀,则无法嵌入appex。
最终订单应如下所示:
plutil
的总像是这样的:
-replace keypath -type value
那就这样做吧
plutil -replace \
CFBundleIdentifier -string \
$PRODUCT_BUNDLE_IDENTIFIER.contentExt \
"$BUILT_PRODUCTS_DIR/contentExt.appex/Info.plist"
如果您想了解更多有关plutil
的信息(请参阅here和here)。 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都转储到一个目录中,然后从那里引用它们。但是为了简单起见,我不这样做。
还要确保您看到original gist更加聪明,如果您使用它来更改所有appexes。您只需传递appex的名称,然后它将找出其余的...