使用CocoaPod依赖项构建Cocoa Touch框架,不要嵌入。

5

我有一个构建成CocoaTouch Framework的SDK。

这个SDK使用了CocoaPods,因为它依赖于一些其他库。我使用以下构建脚本构建框架:

# 1
# Set bash script to exit immediately if any commands fail.
set -e
# 2
# Setup some constants for use later on.
FRAMEWORK_NAME="MyFrameworkName"
OUTPUT_DIR="${SRCROOT}/framework/build"
# 3
# If remnants from a previous build exist, delete them.
if [ -d "${OUTPUT_DIR}" ]; then
rm -rf "${OUTPUT_DIR}"
fi
# 4
# Build the framework for device and for simulator (using
# all needed architectures).
xcodebuild -workspace "${FRAMEWORK_NAME}.xcworkspace" -scheme "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos" -derivedDataPath "${OUTPUT_DIR}"
xcodebuild -workspace "${FRAMEWORK_NAME}.xcworkspace" -scheme "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator" -derivedDataPath "${OUTPUT_DIR}"
# 5
# Remove .framework file if exists from previous run.
if [ -d "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework" ]; then
rm -rf "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"
fi
# 6
# Copy the device version of framework.
cp -r "${OUTPUT_DIR}/Build/Products/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework"
# 7
# Replace the framework executable within the framework with
# a new version created by merging the device and simulator
# frameworks' executables with lipo.
lipo -create -output "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${OUTPUT_DIR}/Build/Products/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${OUTPUT_DIR}/Build/Products/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
# 8
# Copy the Swift module mappings for the simulator into the
# framework. The device mappings already exist from step 6.
cp -r "${OUTPUT_DIR}/Build/Products/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${OUTPUT_DIR}/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule"

所有的都很正常,使用这个框架也不是问题。但是因为这个框架是用其他依赖项构建的,例如 Alamofire 和 Firebase,所以在 MyFrameworkName.framework 中会有这些痕迹。

当我运行一个使用这个框架和 CocoaPods 将所需的依赖项添加到项目中的应用程序时,我会遇到以下错误:

objc[7299]: Class APMPBDynamicFilterResultTimestamp is implemented in both /private/var/containers/Bundle/Application/9966CA12-11F5-42FE-91FF-BB7A91C07571/MyProject.app/Frameworks/MyFrameworkName.framework/MyFrameworkName (0x101b34158) and /var/containers/Bundle/Application/9966CA12-11F5-42FE-91FF-BB7A91C07571/MyProject.app/MyProject (0x1007416e8). One of the two will be used. Which one is undefined.

如何构建具有依赖项的框架(否则它就不能构建),但又不包含其任何内容?

谢谢


1
你考虑过使用 Carthage 来构建你的框架吗?你可以将依赖项设置到 Cartfile 中,并根据需要添加它们。 - alxlives
很不幸,CocoaPods是必需的,否则我早就换了。 - Jeroen
1个回答

1
问题出在你的SDK中使用了cocoapods依赖。正如你所提到的,一切都很好,直到主机应用程序也具有相同的依赖项。不幸的是,由于相同依赖项的符号被链接到SDK和应用程序中,因此没有简单的方法来解决这个问题。但是,您可以考虑以下几种方法:
  1. 如果您愿意通过cocoapods发布SDK,则可以在podspec中指定依赖项。但是,在这种情况下,SDK应该由cocoapods构建。例如podspec example
  2. 另一种方法是向您的SDK添加一个抽象层。您应该使用Bridge模式来处理您的抽象。
我希望这可以帮助到你。

谢谢你的回答。你在第一点中具体指的是什么?我们计划通过CocoaPods提供我们的SDK,但只有那些我们授权访问包含.framework文件的私有repo的人才能使用。你所说的“SDK应该由CocoaPods构建”是什么意思?难道没有一种不嵌入它的构建方式吗?如果我使用一个.framework,显然它是在依赖Foundation/UIKit等的情况下构建的。但这并不会引起冲突。如果可能的话,我该如何实现类似的东西? - Jeroen
我来详细说明一下。当应用程序集成具有依赖关系的SDK时,拥有相同版本的依赖关系非常重要。此外,在某些情况下,它们应该使用相同的构建工具链进行构建。为了实现这一点,您可以在应用程序构建阶段延迟构建您的SDK。其中一个选项是使用Cocoapods。在示例podspec中,有从源代码构建SDK的说明。因此,在集成期间,Cocoapods将确保SDK和应用程序都依赖于相同的依赖项并将它们链接在一起。Foundation/UIKit/etc是系统框架。 - P_O
你的意思是说在构建使用该框架的应用程序时,框架会在用户的机器上构建?在这种情况下,保持源代码关闭/私有非常重要。但我理解得对吗? - Jeroen
是的,没错。在这种情况下,当构建应用程序时,框架将在用户的计算机上构建。顺便问一下,当您将Cocoapods与您的SDK集成时,您是否使用框架? - P_O

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接