如何归档包含自定义框架的应用程序?

我有一个我创build的xcode框架项目,我可以编译成一个myframework.framework文件。 编译完成后,我将这个框架拖放到我的应用程序的Frameworks项目文件夹中,然后使用框架中的类,将正确的import语句添加到任何需要它的类; 这允许我的应用程序成功编译引用框架中定义的类。 为了让应用程序成功部署到我的设备,我还将我的自定义框架添加到我的目标的“embedded二进制文件”部分。 有了这一切,我可以从xcode构build我的应用程序,并在我的设备上运行它。

我试图存档我的应​​用程序的应用程序商店时出现问题。 当我试图做到这一点时,我得到了大量的编译器错误,其中Xcode说它无法find我的自定义框架中定义的任何类的声明。

如何在xcode中设置存档,以便正确引用和embedded我的自定义框架?

你实际上不需要把它放在“embedded式​​二进制文件”部分。 你只需要在“链接的框架和库”部分,确保你的框架是一个通用框架(这意味着它可以编译所有体系结构),并确保你有正确的编译器标志设置(-ObjC如果你的框架有类别等)如果您的框架包含任何c代码,并且您希望在您的客户端应用程序中启用位代码,那么您可能还需要设置其他一些东西,比如“其他C标志”,然后您应该将“-fembed-bitcode”放入您的框架其他C标志这些是我需要做的事情,我的框架应用程序到商店我认为它只是一个误解,你需要把它embedded二进制文件,以及它为商店归档。

这是我用来生成通用框架的构build脚本。 它build立在我的桌面上。 如果你的框架在Swift中,你可以取消注释部分8。 您想要创build一个聚合目标,并在构build阶段将其添加为运行脚本。

 # Merge Script # 1 # Set bash script to exit immediately if any commands fail. set -e # 2 # Setup some constants for use later on. FRAMEWORK_NAME="MyFramework" # 3 # If remnants from a previous build exist, delete them. if [ -d "${SRCROOT}/build" ]; then rm -rf "${SRCROOT}/build" fi # 4 # Build the framework for device and for simulator (using # all needed architectures). xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos" xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator" # 5 # Remove .framework file if exists on Desktop from previous run. if [ -d "${HOME}/Desktop/${FRAMEWORK_NAME}.framework" ]; then rm -rf "${HOME}/Desktop/${FRAMEWORK_NAME}.framework" fi # 6 # Copy the device version of framework to Desktop. cp -r "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${HOME}/Desktop/${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 "${HOME}/Desktop/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/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 "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${HOME}/Desktop/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule" # 9 # Delete the most recent build. if [ -d "${SRCROOT}/build" ]; then rm -rf "${SRCROOT}/build" fi 

一旦你的框架在桌面上,如果你进入它的内部,将会有一个与你的框架同名的文本文档。 如果你导航到,并在terminal上运行命令“lipo -info”,你应该得到以下输出:

 Architectures in the fat file: MyFramework are: armv7 armv7s i386 x86_64 arm64 

不知道现有的答案是否有帮助。 我只是给我的解决scheme。 首先,我想解释几个重要的构build阶段

目标依赖关系

如果你想重build自己的框架(你链接到同一个工作区)每次你build立你的主机应用程序。 你需要在这里添加框架目标。

链接二进制与库

如果你想在你的代码中使用你的库(比如说你想要import MyFramework ),那么你需要在这个阶段链接它。

embedded框架

这是棘手的部分。 embedded意味着在分发时将框架与您的应用程序捆绑在一起。 对于像AVFoundation这样的系统框架,您不需要将其embedded到您的应用程序中,因为它已经存在于iOS操作系统中。 但是,对于您的自定义框架或第三方框架,您必须将它们embedded到应用程序包中,以便在应用程序上部署应用程序时,应用程序可以真正find它。 这就是为什么如果你使用CocoapodsCarthage ,他们都有一个额外的构build阶段来将框架复制到应用程序包。 (对于Cocoapods ,它被称为Embed Pods FrameworkCarthage ,它是一个运行copy-frameworks脚本的动作)。因此,对于您的自定义框架,您可以使用现有的Embed Frameworks构build阶段,或者创build一个New Run Script Phase来复制框架到您的应用程序包。

– 2017-05-17更新 –

对于embedded式框架来说,最近我发现了另一个重要的事实:

您可以使用file PATH/TO/Framework来检查框架是静态的还是dynamic的。 检查这个stackoverflow问题的细节。

dynamic框架

只有dynamic框架需要embedded到应用程序中。 这些包括CarthageCocoapods创造的。 如果您在构build项目后打开应用程序包,则会有一个包含所有embedded式框架的Frameworks文件夹,您可以find由Carthage和Cocoapods创build的文件夹,以及您在Embed Framework阶段中指定的文件夹。

静态框架

那么现在你可能想知道那些静态框架在哪里? 如果应用程序包中缺less它,我们仍然可以使用它? 你是对的。 它们在包中,但不在“ Frameworks文件夹中。 他们已被合并到您的应用程序的可执行文件。 如果你检查可执行文件的大小,每当你为目标添加一个静态框架,它就会增加。

静态框架不需要embedded(只是链接它们),就像一个.swift或一个.swift文件,将被编译到您的可执行文件。


然后,在使用任何框架之前,还有一步要做。 目标版本设置中Framework Search Paths 。 再次,如果你看CarthageCocoapods ,他们都添加额外的path到这个设置。 这告诉Xcode(或底层编译器)在哪里find这些链接embedded的框架。


所以每次你想使用一个框架,确保你想到上面的设置,你都设置好了。 我一直在使用这种方法一段时间,并感到更有信心,当我遇到任何链接问题。


最后,有一篇非常重要的文章,你应该阅读https://developer.apple.com/library/content/technotes/tn2435/_index.html