仅iOS8支持Xcode 6和嵌入式框架


68

当在Xcode 6.0.1中使用嵌入式框架(dyld)且部署目标小于iOS 8时,我得到:

  • 构建成功
  • 运行时库加载错误

错误:

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) 

1
:是的,你可以用在iOS 7的动态框架quellish.tumblr.com/post/103107323582/...
quellish

@quellish很高兴知道,在WWDC '14上与Apple工程师进行了交谈。他们没有建议这种技术。也就是说,在某些情况下,这可能是一个可行的解决方法。
loretoparisi 2014年

Answers:


39

一段时间以来,我一直以为这也是我的问题,但是对于普通应用(非iOS-8扩展),您只需要在随便的Xcode 6 iOS Universal Framework目标中更改一个构建设置即可(设置Mach-O类型到静态库):

Set it to Static Library

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


这不起作用,并且在验证iPA时发出错误。
拉维·达米亚

5
验证时显示“发现意外的Mach-O标头代码:someNumbers ..”。
拉维·达米亚

2
我并没有进行应用程序审查,但这对我一直有效,一直将二进制文件提交到iTunes connect。
安东尼

1
与Anthony所说的类似,我也可以使用此方法针对iTunes Connect验证ipa。该应用程序还可以在iOS 7设备和iOS 8设备上运行,仅需进行一些简短的测试即可。好答案。
强尼

提交给Appstore的任何人都可以批准吗?
natanavra

30

因此,在深入研究之后,我提出了解决方案

应该将您的MyEmbeddedFramework.framework添加到应用程序中,执行此操作

  1. 在“常规”>“嵌入式二进制文件”选项卡中,删除MyEmbeddedFramework.framework
  2. 如果您在那里有MyEmbeddedFramework.framework,则删除“构建阶段”>“复制阶段”“框架”。
  3. 清理构建文件夹
  4. 在无效的嵌入式框架部分中移动MyEmbeddedFramework.framework。
  5. 现在您将看到XCode6创建了一个新的Build Phase> Embedded Frameworks(不是您,它是自动完成的)
  6. 现在,如果您有5个,它应该可以正常运行。

综上所述,要使其正常工作,您应该在以下位置查看MyEmbeddedFramework.framework

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

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

我在iPhone5 / iOS8上无法正常工作,而在iPhone4S / iOS7无法正常工作:

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子类型: / private / var / mobile / Applications /中的0x0000000B 739D9C44-3B91-4D4F-805B-83BE66C9CBCA / musiXmatch.app / Frameworks / ObjectiveLyricsTouch2.framework / ObjectiveLyricsTouch2

问题出在EmbeddedFramework中。我不得不

1)将体系结构设置为默认值2)将有效体系结构设置为:armv7,armv7s和armv64(如苹果公司所建议,需要ARMv64才能使嵌入式框架正常工作)。

然后,我可以在带有嵌入式框架的应用程序上运行

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

无论如何,当提交到iTunesConnect时,最低要求版本都会出现一些错误:

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

嵌入式框架问题


12
明确地说,您是说您的结果表明,即使动态框架可以在iOS 7上运行,App Store提交验证程序也会拒绝尝试在iOS 7上使用动态框架的应用程序?
Matt Foley 2014年

3
是的,这正是我在添加了arm64支持后在这里拥有的功能,当您拥有现代的iOS8应用程序时,它会被请求,这意味着至少一个包含的应用程序/小工具plu嵌入式框架(对于Apple文档)。然后iTunes Connect将以这种方式回复。
loretoparisi 2014年

2
我们认为Apple不太希望它们允许它们在iOS7上运行,并在动态框架上实现代码签名问题。
Matt Foley 2014年

据我所知,如果为iOS7构建嵌入式框架,则无法部署嵌入式框架。在开发或Intranet分发环境中,它的工作方式如我在此处所示。
loretoparisi 2014年

1
“无效的嵌入式框架”部分的位置在哪里。在Xcode中?我看不到一般情况下
xta 2015年

12

截至目前,尚无法使用嵌入式框架在应用程序和小部件之间共享代码,并且无法使其在iOS 8以及iOS 7及更低版本上运行。

这是有关该http://atomicbird.com/blog/ios-app-extension-tips的更多阅读内容

框架与iOS 7

如果要在应用程序和扩展之间共享代码,一种不错的方法是创建自己的嵌入式框架来保存代码。在iOS 8上,这两种情况都会动态加载,因此您已设置好。

如果您仍支持iOS 7(或更早版本),则不是很明确。嵌入式框架在那里不起作用。《 App Extension编程指南》轻松地指出,您可以使用dlopen来解决此问题。使用这种方法,如果您已验证代码正在支持的iOS版本上运行,则可以编写代码以在运行时动态加载框架,而不必依靠iOS为其加载代码。

但是如何在iOS 7上使用该代码?你不知道 如果您的共享代码在嵌入式框架中,则无法在iOS 7上执行它。它只是不可用。

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

并来自Apple的扩展指南https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

如果从包含的应用程序链接到嵌入式框架,则即使嵌入式框架在这些版本中不可用,仍可以将其部署到8.0之前的iOS版本。


BigCheesy我已经阅读了dlopen的文档,但是不了解。我可以在iOS7中使用嵌入式框架
user1010819 2014年

@ user1010819 iOS 7运行时-否 使用主要应用的部署目标iOS 7-是
Mike Glukhov 2015年

4

修复了xcode 6.1.1中的错误

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

在文件末尾(搜索8.1),将出现Begin XCBuildConfiguration部分。

寻找您的框架。

在极端情况下,即使通过目标设置中的Xcode-> general将部署目标设置为7.1,文件中的条目对于调试和发布都具有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:警告:嵌入式dylibs / frameworks仅在iOS 8或更高版本上运行

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


1
您确认提交过程中未拒绝它吗?
hammett 2015年

不起作用,并且版本在病房之后也能正确显示。
拉维达米亚

这是此页面上唯一对我有用的答案。只需将IPHONEOS_DEPLOYMENT_TARGET从8.2更改为7.1,保存项目文件即可成功构建。谢谢。
John Rogers 2015年

4

更深入地了解Apple文档,我发现了有关dlopen命令的信息,该命令用于在某些情况下链接库,具体取决于系统版本和支持的库。

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

因此,让我们看一下Apple Docs提供的解决方案:

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

如果从包含的应用程序链接到嵌入式框架,则即使嵌入式框架在这些版本中不可用,仍可以将其部署到8.0之前的iOS版本。

允许您执行此操作的机制是dlopen命令,您可以使用该命令有条件地链接和加载框架包。您可以使用此命令来替代可以在Xcode GeneralBuild Phases目标编辑器中指定的构建时链接。主要思想是仅在iOS 8.0或更高版本中运行时,才将嵌入式框架链接到您的包含应用程序

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

调用dlopen之后,使用以下类型的语句访问嵌入式框架类:

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

重要

如果包含的应用程序目标链接到嵌入式框架,则它必须包含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命令使用嵌入式框架。您必须像直接调用dlopen一样,限制对这些API的使用。这些API来自CFBundleRef不透明类型:

CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames

从NSBundle类中:

加载
loadAndReturnError:
classNamed:

在要部署到8.0之前的iOS版本的包含应用程序中,仅在确保您在iOS 8.0或更高版本中运行的运行时检查中调用这些API,然后使用Objective-C调用这些API。


2

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

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

该应用程序在所有这三种设备上均能正常工作,但在编译时Xcode中会出现警告。“嵌入式dylibs / frameworks仅在iOS 8或更高版本上运行”

另外,我尝试将应用程序存档,以便将其提交到应用程序商店,但一切正常。

另外,发现了一个链接,该链接在苹果开发人员中指出这是一个错误 https://devforums.apple.com/message/999579#999579


虽然当我们去使用分发配置文件并尝试将应用程序提交到itunesconnect。它发出错误框架“ ...”的MinimumOSVersion无效。最小值是iOS 8.0;
拉维·达米亚

2

仅作记录...将项目从iOS8更改为iOS7部署类型时遇到此问题。

该应用程序使用了cocoapods,并且没有自定义的嵌入式框架。

我不得不更改主项目的两个目标
Application
Application-Test

将Mach-O类型更改为静态(来自以上答案)。

然后在cocoapods项目上。在每个子Pod项目下,将Mach-O类型更改为静态,而将主Pod Project Mach-O设置保留为空白。


2

我将Mach-O类型设置为EXECUTABLE,它对我有用。将其设置为“静态”,“动态”或“捆绑包”时,会产生其他错误。

目标>“您的应用”>构建设置>链接> Mach-O类型>可执行


在ios 9.3.2上也为我工作,这只是解决方案。
DzungPV '16

1

我通过以下方式解决此问题: 在目标“嵌入式框架”和“主应用程序”目标中使用相同的部署目标。


1

所以,暂时的,我对动态库说不,而iOS 7上有很多设备。我如何解决我的问题。我需要lib才能在应用程序和扩展之间传输模型。因此,我将模型以JSON字符串放入共享容器中。它就像一个魅力。


这是序列化/反序列化对象模型并通过容器应用程序和扩展共享它的好选择。问题是,如果您有一个更复杂的框架,并且需要共享逻辑。通过扩展和应用程序的嵌入式二进制文件所在的沙箱,您可以共享文件系统文件夹,因此也可以共享整个数据库。
loretoparisi 2014年

0

在ios上使用动态库时,必须对库进行代码签名。在Xcode 6中,您应该选择“代码登录副本”。对于Xcode5,您应该使用运行脚本自行签名库。喜欢 :

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

这确实可行,因为这样做可以使您的应用程序运行。但是苹果可能不允许这样做。
iOkay 2015年

是的,这确实可以使应用程序运行,但是在itunesconnect的验证过程中失败。
拉维·达米亚

0

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

同样在此之后,我必须在桥接文件中添加框架的所有.h文件,从而解决了该问题。同时从swift文件中删除导入的TestLibrary


0

更新到xcode 7.3时出现错误。而且我有解决方案。-在pods项目中更改目标-> 7.0-希望它有用! 攻击


0

我遇到了一个问题,我需要将一些库作为嵌入式框架包括在内,否则会收到上述错误,而当我这样做时,提交给应用商店时会收到错误。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.