objective-c Xcode 6 和嵌入式框架仅在 iOS8 中受支持
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25909870/
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
Xcode 6 and Embedded Frameworks only supported in iOS8
提问by loretoparisi
When using an embedded framework (dyld) in Xcode 6.0.1 with deployment target less that iOS 8 I get:
在 Xcode 6.0.1 中使用嵌入式框架 (dyld) 时,部署目标低于 iOS 8,我得到:
- Build is successful
- Runtime library loading error
- 构建成功
- 运行时库加载错误
Error:
错误:
dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2
Referenced from: /private/var/mobile/Containers/Bundle/Application/DC65ACA9-98E5-46CD-95F8-829D3416F6C0/musiXmatch.app/musiXmatch
Reason: image not found
(lldb)
采纳答案by Maciek Czarnik
For some time I was thinking that this is my problem as well, but for normal apps (non-iOS-8-extension) you just need to change one build setting in your casual Xcode 6 iOS Universal Framework target (set Mach-O Type to Static Library):
有一段时间我认为这也是我的问题,但是对于普通应用程序(非 iOS-8-extension),您只需要在您的临时 Xcode 6 iOS 通用框架目标中更改一个构建设置(set Mach-O Type到静态库):


There should be no problem with iTunes Connect and iOS 7 after that :)
之后 iTunes Connect 和 iOS 7 应该没有问题:)
回答by loretoparisi
So, after digging around I came out with the solution
所以,在挖掘之后我想出了解决方案
Supposed to have yours MyEmbeddedFramework.framework to add to the app, do this
假设将您的 MyEmbeddedFramework.framework 添加到应用程序中,请执行以下操作
- Remove MyEmbeddedFramework.framework in the tab General > Embedded Binaries
- Remove the Build Phases > Copy Phase "Frameworks" if you have MyEmbeddedFramework.framework there.
- Clean Build Folder
- Move the MyEmbeddedFramework.framework in the void Embedded Frameworks section.
- You will see now that a new Build Phase > Embedded Frameworks is created by XCode6 (not you, it is done automatically)
- Now if you have 5, it should run without erros.
- 在选项卡 General > Embedded Binaries 中删除 MyEmbeddedFramework.framework
- 如果那里有 MyEmbeddedFramework.framework,请删除 Build Phases > Copy Phase "Frameworks"。
- 清理构建文件夹
- 在 void Embedded Frameworks 部分移动 MyEmbeddedFramework.framework。
- 您现在将看到 XCode6 创建了一个新的 Build Phase > Embedded Frameworks(不是您,它是自动完成的)
- 现在,如果您有 5 个,它应该可以无错误地运行。
So to recap, to make it works you should see MyEmbeddedFramework.framework in
所以回顾一下,为了让它工作,你应该看到 MyEmbeddedFramework.framework 在
A) General > Embedded Binaries

A) 常规 > 嵌入式二进制文件

B) Build Phase > Embedded Frameworks

B) 构建阶段 > 嵌入式框架

It worked fine on iPhone5/iOS8not on iPhone4S/iOS7where I get:
它在iPhone5/iOS8上运行良好,而不是在iPhone4S/iOS7 上,我得到:
dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2 Referenced from: /var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/musiXmatch Reason: no suitable image found. Did find: /private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2: incompatible cpu-subtype: 0x0000000Bin /private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2
dyld:库未加载:@rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2 引用自:/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/musiXmatch 原因:找不到合适的图像。确实发现:/private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2:不兼容的CPU亚型:0x0000000B在/私营/无功/移动/应用/ 739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2
The problem was in the EmbeddedFramework. I had to
问题出在 EmbeddedFramework 中。我不得不
1) Set Architecture to default 2) Set Valid Architectures to: armv7, armv7s and armv64 (as Apple suggests armv64 is needed to have Embedded Frameworks working).
1) 将架构设置为默认值 2) 将有效架构设置为:armv7、armv7s 和 armv64(因为 Apple 建议需要 armv64 才能使嵌入式框架工作)。
Then I was able to run the app with an embedded framework on
然后我就能够运行带有嵌入式框架的应用程序
- iPhone5S/iPhone5C iOS8
- iPhone5S/iPhone5C iOS7
- iPod 5th gen / iOS7
- iPhone4S / iOS7
- iPhone4 / iOS7
- iPhone5S/iPhone5C iOS8
- iPhone5S/iPhone5C iOS7
- iPod 第 5 代 / iOS7
- iPhone4S / iOS7
- iPhone4 / iOS7
Anyways when submitting to iTunesConnect I get some errors for the Minimum Required Version:
无论如何,当提交到 iTunesConnect 时,我收到了最低要求版本的一些错误:
- The MinimumOSVersion of framework "..." is invalid. The minimum value is iOS 8.0;
- Invalid Architecture: Apps that include and app extension and a framework must support arm64;
- 框架“...”的 MinimumOSVersion 无效。最小值为 iOS 8.0;
- 无效架构:包含应用程序扩展和框架的应用程序必须支持 arm64;


回答by BigCheesy
As of right now there is no way to use an embedded framework to share code between an app and widget and have it run on iOS 8 as well as iOS 7 & previous.
截至目前,还没有办法使用嵌入式框架在应用程序和小部件之间共享代码并让它在 iOS 8 以及 iOS 7 及之前版本上运行。
Here's some more reading on that http://atomicbird.com/blog/ios-app-extension-tips
这里有更多关于http://atomicbird.com/blog/ios-app-extension-tips 的阅读
Frameworks vs. iOS 7
If you are sharing code between an app and an extension, one nice way to do so is to create your own embedded framework to hold the code. On iOS 8 it'll load dynamically for both cases, so you're set.
If you still support iOS 7 (or earlier), it's not so clear cut. Embedded frameworks don't work there. The App Extension Programming Guide breezily notes that you can use dlopen to deal with this. With that approach you write code to load the framework dynamically at run time rather than rely on iOS loading it for you, if you've verified that the code is running on a version of iOS that supports doing so.
But how do you use that code on iOS 7? You don't. If your shared code is in an embedded framework, there's no way to execute it on iOS 7. It's just unavailable.
The dlopen approach might be handy if you only need the shared code on iOS 8. If you need it on iOS 7, you'll need to include it in the app target. And once you do that, you have no need of the framework. You could still use a framework for the app extension, but doing so is not actually useful. You'd be doing the work of creating the framework but not getting any benefit from it. Just include the shared code in both targets.
框架与 iOS 7
如果您在应用程序和扩展程序之间共享代码,一种很好的方法是创建自己的嵌入式框架来保存代码。在 iOS 8 上,它会在两种情况下动态加载,所以你已经设置好了。
如果您仍然支持 iOS 7(或更早版本),那就不是很清楚了。嵌入式框架在那里不起作用。App Extension Programming Guide 轻松地指出您可以使用 dlopen 来处理这个问题。使用这种方法,您可以编写代码在运行时动态加载框架,而不是依赖 iOS 为您加载它,前提是您已验证代码在支持这样做的 iOS 版本上运行。
但是您如何在 iOS 7 上使用该代码?你没有。如果您的共享代码在嵌入式框架中,则无法在 iOS 7 上执行它。它只是不可用。
如果您只需要 iOS 8 上的共享代码,dlopen 方法可能会很方便。如果您在 iOS 7 上需要它,则需要将它包含在应用程序目标中。一旦你这样做了,你就不需要框架了。您仍然可以为应用程序扩展使用框架,但这样做实际上并没有用。您将从事创建框架的工作,但不会从中获得任何好处。只需在两个目标中包含共享代码。
And from Apple's extension guide https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf
来自 Apple 的扩展指南https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf
If you link to an embedded framework from your containing app, you can still deploy it to versions of iOS older than 8.0, even though embedded frameworks are not available in those versions.
如果您从包含的应用程序链接到嵌入式框架,您仍然可以将其部署到 8.0 之前的 iOS 版本,即使嵌入式框架在这些版本中不可用。
回答by E-Riddie
Going deeper on Apple DocumentationI found out about dlopencommand, which is used to make the linking of the libraries on some conditions, depending on system versions and libraries supported.
深入了解Apple 文档,我发现了dlopen命令,该命令用于在某些条件下链接库,具体取决于系统版本和支持的库。
dlopen example of use: Is the function 'dlopen()' private API?
dlopen 使用示例: 函数 'dlopen()' 是私有 API 吗?
So let's look at the solution provided by Apple Docs:
那么我们来看看Apple Docs提供的解决方案:
Deploying a Containing App to Older Versions of iOS
将包含的应用程序部署到旧版本的 iOS
If you link to an embedded framework from your containing app, you can still deploy it to versions of iOS older than 8.0, even though embedded frameworks are not available in those versions.
如果您从包含的应用程序链接到嵌入式框架,您仍然可以将其部署到 8.0 之前的 iOS 版本,即使嵌入式框架在这些版本中不可用。
The mechanism that lets you do this is the dlopencommand, which you use to conditionally link and load a framework bundle. You employ this command as an alternative to the build-time linking you can specify in the Xcode Generalor Build Phasestarget editor. The main idea is to link embedded frameworks into your containing app only when running in iOS 8.0 or newer.
允许您执行此操作的机制是dlopen命令,您可以使用该命令有条件地链接和加载框架包。您可以使用此命令作为构建时链接的替代方法,您可以在Xcode General或Build Phases目标编辑器中指定。主要思想是仅当在 iOS 8.0 或更高版本中运行时才将嵌入式框架链接到您的包含应用程序中。
You must use Objective-C, not Swift, in your code statements that conditionally load a framework bundle. The rest of your app can be written in either language, and the embedded framework itself can likewise be written in either language.
在有条件加载框架包的代码语句中,您必须使用 Objective-C 而不是 Swift。应用程序的其余部分可以用任何一种语言编写,嵌入式框架本身也可以用任何一种语言编写。
After calling dlopen, access the embedded framework classes using the following type of statement:
调用dlopen 后,使用以下类型的语句访问嵌入式框架类:
MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];
IMPORTANT
If your containing app target links to an embedded framework, it must include the arm64 architecture or it will be rejected by the App Store.
重要的
如果您的包含应用程序目标链接到嵌入式框架,则它必须包含 arm64 架构,否则将被 App Store 拒绝。
To set up an app extension Xcode project to take advantage of conditional linking
设置应用程序扩展 Xcode 项目以利用条件链接
- For each of your contained app extensions, set the deployment target to be iOS 8.0 or later, as usual. Do this in the “Deployment info” section of the General tab in the Xcode target editor.
- For your containing app, set the deployment target to be the oldest version of iOS that you want to support.
- In your containing app, conditionalize calls to the dlopen command within a runtime check for the iOS version by using the systemVersion method. Call the dlopen command only if your containing app is running in iOS 8.0 or later. Be sure to use Objective-C, not Swift, when making this call.
- 对于您包含的每个应用程序扩展,像往常一样将部署目标设置为 iOS 8.0 或更高版本。在 Xcode 目标编辑器的 General 选项卡的“Deployment info”部分执行此操作。
- 对于包含的应用程序,将部署目标设置为您想要支持的最旧版本的 iOS。
- 在您包含的应用程序中,使用 systemVersion 方法在 iOS 版本的运行时检查中对 dlopen 命令的调用进行条件化。仅当您的包含应用程序在 iOS 8.0 或更高版本中运行时才调用 dlopen 命令。进行此调用时,请务必使用 Objective-C,而不是 Swift。
Certain iOS APIs use embedded frameworks via the dlopen command. You must conditionalize your use of these APIs just as you do when calling dlopendirectly. These APIs are from the CFBundleRefopaque type:
某些 iOS API 通过 dlopen 命令使用嵌入式框架。您必须像直接调用dlopen一样对这些 API 的使用进行条件限制。这些 API 来自CFBundleRef不透明类型:
CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames
CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames
And from the NSBundle class:
从 NSBundle 类中:
load
loadAndReturnError:
classNamed:
加载
loadAndReturnError:
classNamed:
In a containing app you are deploying to versions of iOS older than 8.0, call these APIs only within a runtime check that ensures you are running in iOS 8.0 or newer, and call these APIs using Objective-C.
在您部署到 8.0 之前的 iOS 版本的包含应用程序中,仅在确保您在 iOS 8.0 或更高版本中运行的运行时检查中调用这些 API,并使用 Objective-C 调用这些 API。
回答by Gamma-Point
Fixed the error in xcode 6.1.1
修复了 xcode 6.1.1 中的错误
using vim or vi open the project.pbxproj file.
使用 vim 或 vi 打开 project.pbxproj 文件。
At the end of the file (search for 8.1) , there would be Begin XCBuildConfiguration section
在文件的末尾(搜索 8.1),会有 Begin XCBuildConfiguration 部分
Look for your framework.
寻找你的框架。
In out case even though the deployment target was set to 7.1 via Xcode -> general in target settings, the entry in the file had 8.1 for both debug & release
在out情况下,即使部署目标通过Xcode设置为7.1 - >目标设置中的常规,文件中的条目对于调试和发布都有8.1
Here's the old file section looks like:
这是旧文件部分的样子:
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
New section looks like :
新部分看起来像:
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
Now we don't get error just a warning (but works on iOS 7.1 device) : ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
现在我们不会得到错误只是一个警告(但适用于 iOS 7.1 设备):ld:警告:嵌入式 dylibs/frameworks 仅在 iOS 8 或更高版本上运行
This looks like an xcode bug which incorrectly sets different ios targets and then causes error.
这看起来像是一个 xcode 错误,它错误地设置了不同的 ios 目标,然后导致错误。
回答by Ravi Dalmia
We tried running the latest code on the following configurations:
我们尝试在以下配置上运行最新代码:
iOS 8+ — iPhone 5s iOS 7.1.2 — iPhone 4 iOS 6.1.3 — iPad 4
iOS 8+ — iPhone 5s iOS 7.1.2 — iPhone 4 iOS 6.1.3 — iPad 4
The App is working fine on all the three devices but the warning is present in the Xcode while compiling . "embedded dylibs/frameworks only run on iOS 8 or later”
该应用程序在所有三个设备上都运行良好,但在编译 . “嵌入式 dylibs/frameworks 只能在 iOS 8 或更高版本上运行”
Also I tried to Archive the App in order to submit it to the app store it went on fine.
此外,我尝试存档应用程序,以便将其提交到应用程序商店,它运行良好。
Also, found out a link where in an apple developer stated this to be a bug https://devforums.apple.com/message/999579#999579
另外,发现了一个链接,其中苹果开发人员指出这是一个错误 https://devforums.apple.com/message/999579#999579
回答by StuartM
Just for the record... I had this issue when changing a project from iOS8 to iOS7 deployment type.
只是为了记录......我在将项目从 iOS8 更改为 iOS7 部署类型时遇到了这个问题。
The app used cocoapods and no custom embedded frameworks.
该应用程序使用 cocoapods,没有自定义嵌入式框架。
I had to change the main project two targets
Application
Application-Test
我不得不改变主项目的两个目标
Application
Application-Test
Changing Mach-O Type to static (from above answer).
将 Mach-O 类型更改为静态(来自上述答案)。
Then on the cocoapods project. Under each sub pod project changing the Mach-O type to static, leaving the main pod Project Mach-O setting to blank.
然后是 cocoapods 项目。在每个子 pod 项目下,将 Mach-O 类型更改为静态,将主 pod 项目 Mach-O 设置保留为空白。
回答by ctw
I set the Mach-O Type to EXECUTABLE and it worked for me. Setting it to Static, Dynamic or Bundle created other errors when I ran it.
我将 Mach-O 类型设置为 EXECUTABLE,它对我有用。当我运行它时,将它设置为静态、动态或捆绑会产生其他错误。
Target > "Your App" > Build Settings > Linking > Mach-O Type > Executable
目标 > “您的应用程序” > 构建设置 > 链接 > Mach-O 类型 > 可执行文件
回答by Payal Maniyar
I solve this problem following way : Use same deployment target in both target "Embedded Framework" and "main App" target.
我通过以下方式解决了这个问题: 在目标“嵌入式框架”和“主应用程序”目标中使用相同的部署目标。
回答by Andrey Gagan
So, temporary, i said no to dynamic library, while many devices on iOS 7. How i solved my problem. I was need lib for transferring model between app and extension. So, i put my model to JSON string into shared container. And it works like a charm.
所以,暂时,我对动态库说不,而 iOS 7 上的许多设备。我如何解决我的问题。我需要 lib 在应用程序和扩展程序之间传输模型。所以,我将我的模型放入共享容器中的 JSON 字符串。它就像一个魅力。

