Xcode 6和embedded式框架仅在iOS8中受支持

当在Xcode 6.0.1中使用embedded式框架(dyld)并且部署目标less于iOS 8时,我会得到:

  • build立成功
  • 运行时库加载错误

错误:

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) 

一段时间以来,我一直在想这也是我的问题,但对于普通的应用程序( 非iOS-8扩展 ),只需要在随意的Xcode 6 iOS通用框架目标( 设置Mach-Otypes到静态库 ):

将其设置为静态库

之后,iTunes Connect和iOS 7应该没有问题:)

所以,经过挖掘,我提出了解决scheme

假设有您的MyEmbeddedFramework.framework添加到应用程序,请执行此操作

  1. 在General> Embedded Binaries选项卡中删除MyEmbeddedFramework.framework
  2. 如果您有MyEmbeddedFramework.framework,请移除“构build阶段”>“复制阶段”“框架”。
  3. 清理生成文件夹
  4. 将虚拟embedded式框架部分中的MyEmbeddedFramework.framework移动。
  5. 现在你会看到XCode6创build了一个新的构build阶段>embedded式框架(不是你,它是自动完成的)
  6. 现在,如果你有5,它应该没有erros运行。

所以要回顾一下,为了使它工作,你应该看到MyEmbeddedFramework.framework

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

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

它在iPhone5 / iOS8上正常工作, 不是在iPhone4S / iOS7上 ,我得到:

dyld:Library未加载:@ rpath / ObjectiveLyricsTouch2.framework / ObjectiveLyricsTouch2引用自:/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/musiXmatch原因:找不到合适的图像。 find/private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2:incompatible cpu-subtype:0x0000000B in / private / var / mobile / Applications / 739D9C44-3B91-4D4F-805B-83BE66C9CBCA / musiXmatch.app /框架/ ObjectiveLyricsTouch2.framework / ObjectiveLyricsTouch2

问题出在EmbeddedFramework上。 我不得不

1)将体系结构设置为默认设置2)将有效体系结构设置为:armv7,armv7s和armv64(苹果公司build议需要armv64才能使embedded式框架工作)。

然后,我就可以运行带有embedded式框架的应用程序

  • iPhone5S / iPhone5C iOS8
  • iPhone5S / iPhone5C iOS7
  • iPod第五代/ iOS7
  • iPhone4S / iOS7
  • iPhone4 / iOS7

无论如何,当提交到iTunesConnect我得到一些错误的最低要求的版本:

  • 框架的MinimumOSVersion“…”是无效的。 最小值是iOS 8.0;
  • 无效的体系结构:包含应用程序扩展和框架的应用程序必须支持arm64;

嵌入式框架问题

到目前为止,还没有办法使用embedded式框架来共享应用程序和小部件之间的代码,并使其在iOS 8以及iOS 7和之前的版本上运行。

这里有更多的阅读http://atomicbird.com/blog/ios-app-extension-tips

框架与iOS 7

如果您在应用程序和扩展程序之间共享代码,一个好方法是创build自己的embedded式框架来保存代码。 在iOS 8上,它会为两种情况dynamic加载,因此您将被设置。

如果您仍然支持iOS 7(或更早版本),则不太清楚。 embedded式框架在那里不起作用。 应用程序扩展编程指南轻松地注意到,你可以使用dlopen来处理这个问题。 通过这种方法,您可以编写代码来在运行时dynamic加载框架,而不是依赖iOS为您加载它,前提是您已validation代码在支持此操作的iOS版本上运行。

但是,您如何在iOS 7上使用该代码? 你没有。 如果您的共享代码位于embedded式框架中,则无法在iOS 7上执行它。它只是不可用。

如果您只需要iOS 8上的共享代码,则dlopen方法可能会很方便。如果您在iOS 7上需要共享代码,则需要将其包含在应用程序目标中。 一旦你这样做,你就不需要这个框架。 你仍然可以使用框架来扩展应用程序,但是这样做实际上并不有用。 你会做创build框架的工作,但没有从中获得任何好处。 只需在两个目标中包含共享代码即可。

并从苹果的扩展指南https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

如果您从包含的应用程序链接到embedded式框架,即使embedded式框架在这些版本中不可用,仍然可以将其部署到超过8.0的iOS版本。

修复了xcode 6.1.1中的错误

用vim或vi打开project.pbxproj文件。

在文件的末尾(search8.1),将会有Begin XCBuildConfiguration部分

寻找你的框架。

即使通过目标设置中的Xcode – > general将目标部署设置为7.1,对于debugging和发布,文件中的条目也都是8.1

这里的旧文件部分如下所示:

 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 = ""; 

新的部分看起来像:

 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 = ""; 

现在,我们不会只是一个警告(但适用于iOS 7.1设备)的错误:ld:warning:embedded式dylibs /框架只能在iOS 8或更高版本上运行

这看起来像一个错误地设置不同的ios目标,然后导致错误的xcode错误。

对Apple文档进行更深入的研究,我发现了dlopen命令,这个命令用于在某些条件下build立链接库,具体取决于系统版本和支持的库。

dlopen使用示例: 函数“dlopen()”是私有API吗?

我们来看一下Apple Docs提供的解决scheme:

将包含的应用程序部署到旧版本的iOS

如果您从包含的应用程序链接到embedded式框架,即使embedded式框架在这些版本中不可用,仍然可以将其部署到超过8.0的iOS版本。

可以让你这样做的机制是用来有条件地链接和加载框架包的dlopen命令。 您可以使用此命令作为您可以在Xcode GeneralBuild Phases目标编辑器中指定的构build时链接的替代方法。 主要想法是只有在iOS 8.0或更高版本中运行embedded式框架才能连接到您的应用程序

您必须在有条件地加载框架包的代码语句中使用Objective-C而不是Swift 。 您的应用程序的其余部分可以用任何一种语言编写,embedded式框架本身也可以用任何一种语言编写。

调用dlopen之后 ,使用以下types的语句访问embedded式框架类:

 MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init]; 

重要

如果包含应用程序目标链接到embedded式框架,则它必须包含arm64体系结构,否则它将被App Store拒绝。

设置应用程序扩展Xcode项目以利用条件链接

  1. 对于每个包含的附加应用信息,像往常一样将部署目标设置为iOS 8.0或更高版本。 在Xcode目标编辑器的“常规”选项卡的“部署信息”部分执行此操作。
  2. 对于您的包含应用程序,请将部署目标设置为您想要支持的最旧版本的iOS。
  3. 在您的应用程序中,通过使用systemVersion方法,在运行时中调用dlopen命令来检查iOS版本。 仅当您的应用程序在iOS 8.0或更高版本中运行时才调用dlopen命令。 在进行这个调用时一定要使用Objective-C,而不是Swift。

某些iOS API通过dlopen命令使用embedded式框架。 您必须像使用直接调用dlopen时那样使用这些API。 这些API来自CFBundleRef不透明types:

CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames

并从NSBundle类:

加载
loadAndReturnError:
classNamed:

在包含的应用程序中,您将部署到版本低于8.0的iOS版本,只能在运行时检查这些API,以确保您在iOS 8.0或更高版本中运行,并使用Objective-C调用这些API。

我们尝试在以下configuration上运行最新的代码:

iOS 8+ – iPhone 5s iOS 7.1.2 – iPhone 4 iOS 6.1.3 – iPad 4

该应用程序在所有三个设备上工作正常,但编译时在Xcode中存在警告。 “embedded式dylib /框架只能在iOS 8或更高版本上运行”

此外,我试图存档应用程序,以提交到应用程序商店它没有问题。

另外,find了一个苹果开发者指出这是一个错误的链接https://devforums.apple.com/message/999579#999579

我将Mach-O Type设置为EXECUTABLE,它对我很有用。 设置为静态,dynamic或捆绑创build其他错误,当我跑它。

目标>“您的应用程序”>“生成设置”>“链接”>“Mach-Otypes”>“可执行文件”

我解决这个问题的方法如下: 在“embedded式​​框架”和“主要应用”目标中都使用相同的部署目标。

所以,暂时的,我说不要dynamic库,而iOS 7上的很多设备。我如何解决我的问题。 我需要在应用程序和扩展之间传递模型的lib。 所以,我把我的模型JSONstring到共享容器。 它就像一个魅力。

只是为了logging…我有这个问题,当从iOS8项目更改为iOS7的部署types。

该应用程序使用cocoapods并没有定制的embedded式框架。

我不得不改变主要项目的两个目标
应用
应用程序testing

将Mach-Otypes更改为静态(从上面的答案)。

然后在cocoapods项目上。 在将Mach-Otypes更改为静态的每个子​​目录项目下,将主要目录Project Mach-O设置留空。

在ios上使用dynamic库时,必须对代码库进行代码签名。 在Xcode 6中,您应该select“代码login复制”。 而在Xcode5中,你应该用自己的脚本来签署库文件。 喜欢 :

 LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}" IDENTITY="iPhone Developer: xxxxx" codesign --verbose --force --sign "$IDENTITY" "$LOCATION/BeeFramework.framework/BeeFramework" 

删除使用框架! 如果您希望框架在iOS 7.0中运行,请从您的PodFile中启动。 即运行pod deintegrate命令,修改您的PodFile,然后重新运行pod install命令

此后,我不得不在桥接文件中添加框架的所有.h文件,解决了这个问题。 还要从swift文件中删除导入的TestLibrary

更新到xcode 7.3时,我有一个错误。 我有解决scheme。 – 更改目标在pods项目 – > 7.0 – 希望它有用! 攻击

我遇到了一个问题,我需要包括一些库作为embedded式框架,否则我收到上述错误,当我这样做,我收到错误时提交到应用程序商店。

我的解决scheme是使用Pods,并确保取消注释“use_frameworks!” 线。