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添加到应用程序,请执行此操作
- 在General> Embedded Binaries选项卡中删除MyEmbeddedFramework.framework
- 如果您有MyEmbeddedFramework.framework,请移除“构build阶段”>“复制阶段”“框架”。
- 清理生成文件夹
- 将虚拟embedded式框架部分中的MyEmbeddedFramework.framework移动。
- 现在你会看到XCode6创build了一个新的构build阶段>embedded式框架(不是你,它是自动完成的)
- 现在,如果你有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框架的工作,但没有从中获得任何好处。 只需在两个目标中包含共享代码即可。
如果您从包含的应用程序链接到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 General或Build Phases目标编辑器中指定的构build时链接的替代方法。 主要想法是只有在iOS 8.0或更高版本中运行embedded式框架才能连接到您的应用程序 。
您必须在有条件地加载框架包的代码语句中使用Objective-C而不是Swift 。 您的应用程序的其余部分可以用任何一种语言编写,embedded式框架本身也可以用任何一种语言编写。
调用dlopen之后 ,使用以下types的语句访问embedded式框架类:
MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];
重要
如果包含应用程序目标链接到embedded式框架,则它必须包含arm64体系结构,否则它将被App Store拒绝。
设置应用程序扩展Xcode项目以利用条件链接
- 对于每个包含的附加应用信息,像往常一样将部署目标设置为iOS 8.0或更高版本。 在Xcode目标编辑器的“常规”选项卡的“部署信息”部分执行此操作。
- 对于您的包含应用程序,请将部署目标设置为您想要支持的最旧版本的iOS。
- 在您的应用程序中,通过使用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!” 线。