iOS - watchOS App 发布问题 CFBundleIdentifier 冲突
iOS - watchOS App publishing issue CFBundleIdentifier collision
应用上传后我收到以下邮件
We identified one or more issues with a recent delivery for your app,
XXX. Please correct the following issues, then upload again.
ITMS-90806: CFBundleIdentifier collision - Each bundle must have a
unique bundle identifier. The bundle identifier
'org.cocoapods.CocoaLumberjack' is used in the bundles
'[CocoaLumberjack.framework, CocoaLumberjack.framework]'
CocoaLumberjack 是一个第三方库,我过去已经用过很多次了,没有任何问题,我很困惑。
与框架的.plist关键字CFBundlePackageType无关
正如此 question/answer 中指定的那样。 CocoaLumberjack 包类型是 "Framework" (CFBundlePackageType = FMWK)。 CocoaLumberjack 是一个广泛使用的第三方库,使用 cocoapods 添加到我的项目中。
这个问题可能与我的应用程序包中的 watchOS 目标有关。
CocoaLumberjack 库在 iOS 应用程序和 watchOS 应用程序中使用,它导致了有关包标识符重复的问题。
如果 iOS 目标和 Watch Extension 之间共享框架,Apple Connect 服务器会检测到 CFBundleIdentifier 冲突。
target 'App' do
platform :ios, '9.0'
# Pods for App
...
pod 'CocoaLumberjack/Swift', '~> 3.5.3'
...
end
target 'AppWatch Extension' do
platform :watchos, '5.0'
# Pods for Watch Extension
...
pod 'CocoaLumberjack/Swift', '~> 3.5.3'
...
end
iOS 应用正在使用该库,而 watchOS 扩展正在使用相同的库。他们使用不同的库,但 CocoaLumberjack 是两者中唯一存在的库。
我过去已经多次发布我的应用程序,相同的库配置没有任何问题。我猜最近几天 Apple 改变了一些关于 bundle identifier 的限制。
使用 Carthage 也存在同样的问题。
只需从您的扩展中删除嵌入框架构建阶段。
单击目标部分中的扩展 -> 构建阶段 -> 删除嵌入 pods 框架
见附图:
作为临时解决方法,我手动重命名了 watchOS 扩展中的包标识符,然后应用程序发布工作正常,但它看起来不是一个好的解决方案,特别是如果你 运行 CI 系统.
更好的选择是在 pod 文件中添加特定的 post 安装操作:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'CocoaLumberjack-watchOS'
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
end
或者如果您必须处理多个库:
post_install do |installer|
watchosLibs = ['Lib1-watchOS', 'Lib2-watchOS', 'Lib3-watchOS']
installer.pods_project.targets.each do |target|
if watchosLibs.include? target.name
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}.${PLATFORM_NAME}"
end
end
end
end
注意重命名 pods 包标识符,否则某些库的行为不正确。
我建议只重命名被 Apple 拒绝的库,以尽量减少可能出现的问题。
目前有一些关于此问题的不同开放线程:
使用 Carthage 而不是 Cocoa 也存在类似问题pods
如果 Apple 不更改有关捆绑包标识符的新政策,那么 cocoapods 团队可能会提供更干净的解决方案。
显然 Apple 更改了验证过程。看起来他们不允许应用程序中的平台特定框架具有相同的标识符。
论坛上也有关于此的 post:https://forums.developer.apple.com/thread/122048
如果您因为使用 Cocoapods 而 运行 陷入这个问题,您可以修补 Podfile 以将平台名称附加到包标识符,以便它们始终是唯一的(source):
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
如果您的应用程序中有多个目标,您可以在 XCode 中更改方案中的 watchOS 目标,并将 .watchos
附加到标识符。
你不需要改变每一个目标,这样写更干净:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.platform_name == :watchos
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
end
以下是我如何解决 Carthage 的问题。
1) 创建一个 Carthage 构建脚本,将不同的 Carthage 构建阶段分开
2) 当您进行实际的框架构建时;首先为 iOS 构建问题框架(我只有一个),然后修改项目文件以更改包标识符,然后为 watchOS 构建这些框架,然后构建其余框架
carthage bootstrap --no-checkout
carthage checkout
#undo previous CFBundleIdentifier changes
sed -i '' 's/com.someco.MyFramework.watchOS;/com.someco.MyFramework;/g' Carthage/Checkouts/MyFramework/MyFramework.xcodeproj/project.pbxproj
carthage build --cache-builds --platform iOS
#set a unique CFBundleIdentifier
sed -i '' 's/com.someco.MyFramework;/com.someco.MyFramework.watchOS;/g' Carthage/Checkouts/MyFramework/MyFramework.xcodeproj/project.pbxproj
carthage build --no-use-binaries --platform watchOS --configuration $CONF $VERBOSE MyFramework
一个选项是 - 您可以手动将“.watchos”(abc.asd.alomofire.watchos
) 添加到手表包标识符。
应用上传后我收到以下邮件
We identified one or more issues with a recent delivery for your app, XXX. Please correct the following issues, then upload again.
ITMS-90806: CFBundleIdentifier collision - Each bundle must have a unique bundle identifier. The bundle identifier 'org.cocoapods.CocoaLumberjack' is used in the bundles '[CocoaLumberjack.framework, CocoaLumberjack.framework]'
CocoaLumberjack 是一个第三方库,我过去已经用过很多次了,没有任何问题,我很困惑。
与框架的.plist关键字CFBundlePackageType无关
正如此 question/answer
这个问题可能与我的应用程序包中的 watchOS 目标有关。 CocoaLumberjack 库在 iOS 应用程序和 watchOS 应用程序中使用,它导致了有关包标识符重复的问题。
如果 iOS 目标和 Watch Extension 之间共享框架,Apple Connect 服务器会检测到 CFBundleIdentifier 冲突。
target 'App' do
platform :ios, '9.0'
# Pods for App
...
pod 'CocoaLumberjack/Swift', '~> 3.5.3'
...
end
target 'AppWatch Extension' do
platform :watchos, '5.0'
# Pods for Watch Extension
...
pod 'CocoaLumberjack/Swift', '~> 3.5.3'
...
end
iOS 应用正在使用该库,而 watchOS 扩展正在使用相同的库。他们使用不同的库,但 CocoaLumberjack 是两者中唯一存在的库。
我过去已经多次发布我的应用程序,相同的库配置没有任何问题。我猜最近几天 Apple 改变了一些关于 bundle identifier 的限制。
使用 Carthage 也存在同样的问题。
只需从您的扩展中删除嵌入框架构建阶段。
单击目标部分中的扩展 -> 构建阶段 -> 删除嵌入 pods 框架
见附图:
作为临时解决方法,我手动重命名了 watchOS 扩展中的包标识符,然后应用程序发布工作正常,但它看起来不是一个好的解决方案,特别是如果你 运行 CI 系统.
更好的选择是在 pod 文件中添加特定的 post 安装操作:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'CocoaLumberjack-watchOS'
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
end
或者如果您必须处理多个库:
post_install do |installer|
watchosLibs = ['Lib1-watchOS', 'Lib2-watchOS', 'Lib3-watchOS']
installer.pods_project.targets.each do |target|
if watchosLibs.include? target.name
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}.${PLATFORM_NAME}"
end
end
end
end
注意重命名 pods 包标识符,否则某些库的行为不正确。
我建议只重命名被 Apple 拒绝的库,以尽量减少可能出现的问题。
目前有一些关于此问题的不同开放线程:
使用 Carthage 而不是 Cocoa 也存在类似问题pods
如果 Apple 不更改有关捆绑包标识符的新政策,那么 cocoapods 团队可能会提供更干净的解决方案。
显然 Apple 更改了验证过程。看起来他们不允许应用程序中的平台特定框架具有相同的标识符。
论坛上也有关于此的 post:https://forums.developer.apple.com/thread/122048
如果您因为使用 Cocoapods 而 运行 陷入这个问题,您可以修补 Podfile 以将平台名称附加到包标识符,以便它们始终是唯一的(source):
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
如果您的应用程序中有多个目标,您可以在 XCode 中更改方案中的 watchOS 目标,并将 .watchos
附加到标识符。
你不需要改变每一个目标,这样写更干净:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.platform_name == :watchos
target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}-$(PLATFORM_NAME)'
end
end
end
end
以下是我如何解决 Carthage 的问题。
1) 创建一个 Carthage 构建脚本,将不同的 Carthage 构建阶段分开
2) 当您进行实际的框架构建时;首先为 iOS 构建问题框架(我只有一个),然后修改项目文件以更改包标识符,然后为 watchOS 构建这些框架,然后构建其余框架
carthage bootstrap --no-checkout
carthage checkout
#undo previous CFBundleIdentifier changes
sed -i '' 's/com.someco.MyFramework.watchOS;/com.someco.MyFramework;/g' Carthage/Checkouts/MyFramework/MyFramework.xcodeproj/project.pbxproj
carthage build --cache-builds --platform iOS
#set a unique CFBundleIdentifier
sed -i '' 's/com.someco.MyFramework;/com.someco.MyFramework.watchOS;/g' Carthage/Checkouts/MyFramework/MyFramework.xcodeproj/project.pbxproj
carthage build --no-use-binaries --platform watchOS --configuration $CONF $VERBOSE MyFramework
一个选项是 - 您可以手动将“.watchos”(abc.asd.alomofire.watchos
) 添加到手表包标识符。