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

Posted

技术标签:

【中文标题】如何归档包含自定义框架的应用程序?【英文标题】:How to archive an app that includes a custom framework? 【发布时间】:2016-02-26 15:32:24 【问题描述】:

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

当我尝试为应用商店归档我的应用程序时,我的问题就出现了。当我尝试这样做时,我得到了大量的编译器错误,其中 xcode 说它找不到我的自定义框架中定义的任何类的声明。

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

【问题讨论】:

我遇到了与此类似的问题,我能找到的唯一解决方法是将整个框架项目作为应用程序项目的子项目导入。很想知道是否有更好的解决方案。 您是否为您的框架导入了标头? @Tanguy:我在哪里/怎么做? 看看这里raywenderlich.com/65964/create-a-framework-for-ios,并尝试找到你错过的一些步骤 @Tanguy:那是我用来构建框架的教程。不幸的是,该教程没有说明如何为应用商店存档项目(正如我在问题中提到的,我能够构建应用并从 Xcode 部署它而没有任何问题)。 【参考方案1】:

您实际上不需要将它放在“嵌入式​​二进制文件”部分。您只需要在“链接的框架和库部分。确保您的框架是通用框架(意味着它可以为所有架构编译),并确保您设置了正确的编译器标志(-ObjC 如果您的框架有任何类别等)如果您的框架包含任何 c 代码并且您想在客户端应用程序中启用位码,那么您可能需要设置一些其他内容,例如“其他 C 标志”,那么您应该将“-fembed-bitcode”放入您的框架其他 C 标志。这些是我需要做的事情才能让我的框架应用程序进入商店。我认为这只是一个误解,你需要将它放入嵌入式二进制文件中,以便将其存档以供商店使用。

这是我用来生成通用框架的构建脚本。它直接构建在我的桌面上。如果您的框架使用 Swift,您可以取消注释第 8 节。您想创建一个聚合目标并将其添加为构建阶段的运行脚本。

# 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

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

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

【讨论】:

好吧,我必须将框架添加到 Embedded Binaries 部分,以便让 app+framework 从 xcode 部署到我的设备(否则它只会编译但在您尝试运行它时会失败因为没有部署框架)。当我从嵌入式二进制文件中删除它时,尝试存档仍然失败,但至少出现不同的错误。 您确定您有一个通用框架,其中“仅构建活动架构”设置为否?构建框架时,请确保构建到“通用 iOS 设备” 我从哪里知道它是否是一个通用框架?我目前将“仅构建活动架构”设置为“是”,并且我正在为特定设备而不是通用设备构建。我会尝试一下这些更改。 感谢您的帮助,我想我快到了(基于我看到的构建错误的变化)。你能告诉我如何将“-fembed-bitcode”放在我框架的其他 C 标志中吗?我在任何地方都找不到“其他 C 标志” - 这是“链接”部分中的“其他链接器标志”吗? 更新了我对完整步骤的回答。如果您的框架在运行 lipo-info 时没有说它具有所有这些架构,那么它不是一个通用库【参考方案2】:

不确定现有答案是否对您有所帮助。我只会给出我的解决方案。首先,我想解释几个重要的构建阶段

目标依赖

如果您想在每次构建宿主应用程序时重新构建自己的框架(链接到同一个工作区)。您需要在此处添加框架目标。

将二进制文件与库链接

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

嵌入框架

这是棘手的部分。 嵌入 意味着在分发时将框架与您的应用程序捆绑在一起。对于系统框架,例如AVFoundation,您不需要将其嵌入到您的应用程序中,因为它已经存在于iOS操作系统中。但是,对于您的自定义框架或第三方框架,您必须将它们嵌入到您的应用程序包中,以便当您在设备上部署应用程序时,应用程序可以实际找到它。这就是为什么如果您使用CocoapodsCarthage,它们都有一个额外的构建阶段来将框架复制到应用程序包。 (对于Cocoapods,它称为Embed Pods Framework,对于Carthage,它是一个运行copy-frameworks 脚本的操作)所以对于您的自定义框架,您可以使用现有的Embed Frameworks构建阶段或创建新的运行脚本阶段以将框架复制到您的应用程序包中。

-- 2017-05-17 更新--

对于嵌入框架的东西,我最近发现了另一个重要的事实:

您可以使用file PATH/TO/Framework 来检查框架是静态的还是动态的。详情请查看this *** question。

动态框架

只有动态框架需要嵌入到应用程序中。其中包括由CarthageCocoapods 创建的那些。如果您在构建项目后打开应用程序包,则会有一个 Frameworks 文件夹,其中包含您所有的嵌入式框架,您会发现 Carthage 和 Cocoapods 创建的那些以及您在嵌入框架阶段指定的那些。

静态框架

所以现在您可能想知道那些静态框架在哪里?如果应用程序包中缺少它,我们如何仍然使用它?你是对的。它们在捆绑包中,但不在 Frameworks 文件夹中。它们已合并到您的应用程序的可执行文件中。如果您检查可执行文件的大小,您会发现每次向目标添加静态框架时,它都会增加。

不必嵌入静态框架(只需链接它们),它就像一个 .swift.xib 文件,将被编译到您的可执行文件中。


然后,在您可以使用任何框架之前,还有一步要走。目标 Build Settings 内部的 Framework Search Paths。同样,如果您查看CarthageCocoapods,它们都会在此设置中添加额外的路径。这告诉 Xcode(或底层编译器)在哪里可以找到这些 linkedembedded 框架。


因此,每次您想使用框架时,请确保您考虑了上述设置并且一切就绪。我使用这种方法已经有一段时间了,当我遇到任何链接问题时会更加自信。


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

【讨论】:

另外,来自 Apple Dev 文档的重要事实:“应用程序目标负责嵌入所有框架,包括其他框架所依赖的任何框架。” - 否则你会遇到嵌套依赖框架的问题,因为它们不会出现在复制步骤中,所以它们不会被签名。【参考方案3】:

我遇到了完全相同的问题。 如果您像我一样使用应用扩展,并且存档错误消息仅与应用扩展相关联。

请记住,您必须手动将自定义框架添加到应用扩展程序的“链接框架和库”部分。

【讨论】:

【参考方案4】:

希望对你有帮助

    在目标中选择您的项目。 2.然后搜索Skip install。 将其更改为 NO。 然后归档您的自定义框架。 (确保使用 Generic iOS Device )作为目标设备。 导出到哪里 你要。然后将其用于您的项目。

【讨论】:

以上是关于如何归档包含自定义框架的应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

创建自定义归档程序?

如何将自定义对象的 NSArray 归档到 Objective-C 中的文件

如何在 Swift 中归档和取消归档自定义对象?或者如何在 Swift 中将自定义对象保存到 NSUserDefaults?

在 Swift 中归档自定义对象 - 扩展

自定义归档格式文件读取

Maven 自定义归档扩展 - 如何使用解包依赖项?