xcode 如何归档包含自定义框架的应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35655698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to archive an app that includes a custom framework?
提问by MusiGenesis
I have an xcode framework project that I've created, which I can compile into a myframework.framework
file. After compiling, I drag this framework into the Frameworks project folder of my application, and then to make use of classes from the framework I add the proper import
statement to any class that needs it; this allows my app to successfully compilewith references to classes defined in the framework. To get the app to deploysuccessfully to my device, I also add my custom framework to the "Embedded Binaries" section for my target. With all this in place, I can build my app from xcode and run it on my device.
我有一个我创建的 xcode 框架项目,我可以将其编译成一个myframework.framework
文件。编译后,我将这个框架拖到我的应用程序的 Frameworks 项目文件夹中,然后为了使用框架中的类,我将正确的import
语句添加到任何需要它的类中;这允许我的应用程序使用对框架中定义的类的引用成功编译。为了使应用程序成功部署到我的设备,我还将自定义框架添加到目标的“嵌入式二进制文件”部分。有了这一切,我可以从 xcode 构建我的应用程序并在我的设备上运行它。
My problem comes when I attempt to Archive my application for the app store. When I attempt to do this, I get a ton of compiler errors where xcode says it cannot find the declarations for any of the classes defined in my custom framework.
当我尝试为应用商店存档我的应用程序时,我的问题就出现了。当我尝试这样做时,我收到了大量编译器错误,其中 xcode 说它找不到我的自定义框架中定义的任何类的声明。
How can I set up Archive in xcode so that it properly references and embeds my custom framework?
如何在 xcode 中设置存档,以便它正确引用和嵌入我的自定义框架?
回答by arc4randall
You actually don't need to put it in the "embedded binaries" section. You only need it in the "linked frameworks and libraries section. Make sure that your framework is a Universal Framework (meaning it can compile for all architectures), and make sure you have the right compiler flags set (-ObjC if your framework has any categories etc) There may be some other things you need to set as well like "Other C Flags" if your framework includes any c code and you want to enable bitcode in your client app then you should put "-fembed-bitcode" in your framework Other C Flags. Those were the things I needed to do to get my framework app to the store. I think its a just a misconception that you need to put this in embedded binaries as well to get it to archive for the store.
您实际上不需要将它放在“嵌入式二进制文件”部分。您只需要在“链接框架和库”部分中使用它。确保您的框架是通用框架(意味着它可以为所有架构编译),并确保您设置了正确的编译器标志(-ObjC,如果您的框架有任何类别等)如果您的框架包含任何 c 代码并且您想在您的客户端应用程序中启用位码,那么您可能还需要设置一些其他的东西,例如“其他 C 标志”,那么您应该将“-fembed-bitcode”放在您的framework 其他 C 标志。这些是我需要做的事情才能让我的框架应用程序进入商店。我认为这只是一个误解,你需要把它放在嵌入式二进制文件中才能让它为商店存档。
This is the build script I use to generate the universal framework. It builds right to my desktop. You can uncomment section 8 if your framework is in Swift. You want to create an aggregate target and add this as a run script in build phases.
这是我用来生成通用框架的构建脚本。它直接构建到我的桌面上。如果您的框架在 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
Once your framework is on the desktop, if you go inside of it there will be a text document with the same name as your framework. If you navigate to that and run the command "lipo -info" on it in terminal you should get the following output:
一旦您的框架在桌面上,如果您进入它,将会有一个与您的框架同名的文本文档。如果你导航到那个并在终端上运行命令“lipo -info”,你应该得到以下输出:
Architectures in the fat file: MyFramework are: armv7 armv7s i386 x86_64 arm64
回答by J.Wang
Not sure if the existing answers help you. I'll just give my solution. First, I want to explain several important Build Phases.
不确定现有答案是否对您有帮助。我只会给出我的解决方案。首先,我想解释几个重要的构建阶段。
Target Dependencies
目标依赖
If you want to rebuild your own framework (which you linked to the same workspace) every time you build your host app. You'll need to added the framework target here.
如果您想在每次构建宿主应用程序时重建自己的框架(链接到同一个工作区)。您需要在此处添加框架目标。
Link Binary With Libraries
将二进制文件与库链接
If you want to use your library in your code (say you want to do import MyFramework
), then you need to linked it in this phase.
如果你想在你的代码中使用你的库(比如你想做import MyFramework
),那么你需要在这个阶段链接它。
Embed Framework
嵌入框架
This is the tricky part. Embedmeans to bundle the framework together with your app when distributing. For a system framework, such as AVFoundation
, you don't need to embed it into your app since it already exists inside the iOS operation system. However, for your custom frameworks or third-party frameworks, you'll have to embed them into your app bundle so that when you deploy your app on the device, the app can actually find it. That's why if you use Cocoapods
or Carthage
, they all have an extra build phase to copy the frameworks to the app bundle. (For Cocoapods
, it's called Embed Pods Frameworkand for Carthage
, it's an action that runs copy-frameworks
script) So for your custom framework, you'll either use the existing Embed Frameworks
build phase or create a New Run Script Phaseto copy the frameworks to your app bundle.
这是棘手的部分。嵌入意味着在分发时将框架与您的应用程序捆绑在一起。对于系统框架,例如AVFoundation
,您不需要将其嵌入到您的应用程序中,因为它已经存在于 iOS 操作系统中。但是,对于您的自定义框架或第三方框架,您必须将它们嵌入到您的应用程序包中,这样当您在设备上部署应用程序时,应用程序才能真正找到它。这就是为什么如果您使用Cocoapods
或Carthage
,它们都有一个额外的构建阶段来将框架复制到应用程序包。(对于Cocoapods
,它称为Embed Pods 框架,对于Carthage
,它是一个运行copy-frameworks
脚本的操作)因此对于您的自定义框架,您将使用现有的Embed Frameworks
构建阶段或创建一个新的运行脚本阶段将框架复制到您的应用程序包。
-- Update on 2017-05-17 --
-- 2017-05-17 更新 --
For the embed framework stuff, there's another important fact I found recently:
对于嵌入框架的东西,我最近发现了另一个重要的事实:
You can use file PATH/TO/Framework
to check whether a framework is static or dynamic. Check this stackoverflow questionfor details.
您可以file PATH/TO/Framework
用来检查框架是静态的还是动态的。有关详细信息,请查看此 stackoverflow 问题。
Dynamic Frameworks
动态框架
Only dynamic frameworks need to be embedded into the app. These include the ones created by Carthage
and Cocoapods
. If you open the app bundle after you build your project, there's a Frameworks
folder that contains all your embedded frameworks and you'll find the ones created by Carthage and Cocoapods as well as the ones you specified in the Embed Framework phase.
只需要将动态框架嵌入到应用程序中。这些包括由Carthage
和创建的Cocoapods
。如果您在构建项目后打开应用程序包,则有一个Frameworks
文件夹包含您所有的嵌入式框架,您将找到由 Carthage 和 Cocoapods 创建的以及您在 Embed Framework 阶段指定的那些。
Static Frameworks
静态框架
So now you might wonder where are those static frameworks? How can we still use it if it's missing from the app bundle? You're right. They are in the bundle but not in the Frameworks
folder. They have been merged into the executable of your app. If you check the size of executable, you'll realise every time you add a static framework to your target, it will increase.
所以现在你可能想知道那些静态框架在哪里?如果应用程序包中缺少它,我们如何仍然使用它?你是对的。它们在捆绑包中,但不在Frameworks
文件夹中。它们已合并到您的应用程序的可执行文件中。如果您检查可执行文件的大小,您会发现每次向目标添加静态框架时,它都会增加。
Static frameworks don't have to be embedded (just Link them), it's like a .swift
or a .xib
file that will be compiled into your executable.
静态框架不必嵌入(只需链接它们),它就像一个.swift
或一个.xib
文件,将被编译成您的可执行文件。
And then, there's one more step to go before you can use any framework. The Framework Search Paths
inside target Build Settings. Again, if you look at Carthage
or Cocoapods
, they all add extra paths into this setting. This tells Xcode (or the underlying compiler) where to find these linkedor embeddedframeworks.
然后,在您可以使用任何框架之前,还有一步要走。该Framework Search Paths
内部目标构建设置。同样,如果您查看Carthage
或Cocoapods
,它们都会在此设置中添加额外的路径。这会告诉 Xcode(或底层编译器)在哪里可以找到这些链接或嵌入的框架。
So every time you'd want to use a framework, make sure you think about the above settings and you're all set. I've been using this method for a while and feel more confident when I encounter any linking issue.
因此,每次您想要使用框架时,请确保考虑上述设置并且您已准备就绪。我已经使用这种方法有一段时间了,当我遇到任何链接问题时会更有信心。
Finally, there's a very important article from Apple you should read https://developer.apple.com/library/content/technotes/tn2435/_index.html
最后,Apple 有一篇非常重要的文章,您应该阅读https://developer.apple.com/library/content/technotes/tn2435/_index.html
回答by Sam
I had the exact same problem. If you use app extension like me, and the archive error message is only associated with the app extension.
我有同样的问题。如果您像我一样使用应用程序扩展程序,并且存档错误消息仅与应用程序扩展程序相关联。
Remember that you have to MANUALLY add your custom framework into the "Linked Frameworks and Libraries" section of your app extension.
回答by Pal Phoo
Hope this will help you
希望能帮到你
- Select your Project in Targets. 2.Then search for Skip install.
- Change it into NO.
- Then archive your custom framework. (make sure to use Generic iOS Device ) as a target device.
- Export it to where you want. Then use it with your project.
- 在目标中选择您的项目。2.然后搜索跳过安装。
- 把它改成NO。
- 然后归档您的自定义框架。(确保使用 Generic iOS Device )作为目标设备。
- 将其导出到您想要的位置。然后在您的项目中使用它。