如何导出"胖"Cocoa Touch Framework(用于模拟器和设备)?

sky*_*der 107 xcode cocoa-touch frameworks ios ios-universal-framework

使用Xcode 6,我们可以创建自己的Dynamic Cocoa Frameworks.

在此输入图像描述

因为:

  • 模拟器仍然使用32-bit

  • 从2015年6月1日开始,提交到App Store的应用更新必须包含64位支持,并使用iOS 8 SDK(developer.apple.com)构建

我们必须使胖库在设备和模拟器上运行项目.即支持Frameworks中的32位和64位.

但我没有找到任何手册,如何导出通用胖框架以便将来与其他项目集成(并与某人共享此库).

以下是我重现的步骤:

  1. 设置ONLY_ACTIVE_ARCH=NOBuild Settings

    在此输入图像描述

  2. 支持添加armv7 armv7s arm64 i386 x86_64Architectures(肯定)

在此输入图像描述

  1. 构建框架并在Finder中打开它:

在此输入图像描述 在此输入图像描述

  1. 将此框架添加到另一个项目中

实际结果:

但最终我仍然遇到在设备和模拟器上同时使用此框架运行项目的问题.

  • 如果我从Debug-iphoneos文件夹中获取框架- 它适用于设备并在模拟器上获取错误:ld: symbol(s) not found for architecture i386

    xcrun lipo -info CoreActionSheetPicker
    
    Run Code Online (Sandbox Code Playgroud)

    胖文件中的体系结构:CoreActionSheetPicker是:armv7 armv7s arm64

  • 如果我从Debug-iphonesimulator文件夹中获取框架- 它适用于模拟器.我在设备上有错误:ld: symbol(s) not found for architecture arm64

    xcrun lipo -info CoreActionSheetPicker
    
    Run Code Online (Sandbox Code Playgroud)

    胖文件中的体系结构:CoreActionSheetPicker是:i386 x86_64

那么,如何创建一个适用于设备和模拟器的动态框架?

这个答案与Xcode 6 iOS相关创建Cocoa Touch Framework - 架构问题但不重复.


更新:

我发现这个案子的"肮脏的黑客".请参阅下面的答案.如果有人知道更方便的方式 - 请告诉我!

Sta*_*ich 79

这个答案的实际情况是:2015年7月.事情很可能会发生变化.

TLDR;

目前Xcode没有自动导出通用脂肪框架的工具,因此开发人员必须求助于手动使用lipo工具.同样根据这个雷达提交给AppStore开发人员之前,框架的消费者也必须使用lipo从框架中剥离模拟器切片.

接下来是更长的答案


我在这个主题上做了类似的研究(答案底部的链接).

我还没有发现有关这样分布的任何正式文件我的研究是基于对苹果开发者论坛,迦太基和领域的项目和我自己的实验探索xcodebuild,lipo,codesign工具.

以下是来自Apple Developer Forums线程的长引用(带有一些标记)来导出带有嵌入式框架的应用程序:

从框架项目中导出框架的正确方法是什么?

目前唯一的方法就是你所做的:

  • 为模拟器和iOS设备构建目标.
  • 导航到该项目的Xcode的DerivedData文件夹,并将两个二进制文件合并为一个单独的框架.但是,在Xcode中构建框架目标时,请确保将目标设置"仅构建活动体系结构"调整为"否".这将允许Xcode为多种binarty类型(arm64,armv7等)构建目标.这就是为什么它可以从Xcode运行而不是作为一个独立的二进制文件.

  • 此外,您还需要确保将方案设置为发布版本,并针对发布构建框架目标.如果仍然出现库未加载错误,请检查框架中的代码片.

  • 使用lipo -info MyFramworkBinary并检查结果.

lipo -info MyFrameworkBinary

结果是 i386 x86_64 armv7 arm64

  • 现代通用框架将包括4个切片,但可能包含更多:i386 x86_64 armv7 arm64 如果您至少看不到这4个,那么可能是因为Build Active Architecture设置.

这描述的过程与@skywinder在回答中的做法非常相似.

这就是Carthage使用lipoRealm使用lipo的方式.


重要细节

有雷达:Xcode 6.1.1和6.2:包含模拟器切片的iOS框架无法提交到App Store,并且在Realm#1163Carthage#188上围绕它进行了长时间的讨论,结束于特殊的解决方法:

在提交到AppStore之前,必须从模拟器切片中删除iOS框架二进制文件

Carthage有特殊代码:CopyFrameworks和相应的文档:

此脚本适用于由通用二进制文件触发的App Store提交错误.

Realm有特殊的脚本:strip-frameworks.sh和相应的文档:

归档通用二进制文件时,需要执行此步骤来解决App Store提交错误.

还有一篇好文章:在Xcode中从动态库中删除不需要的体系结构.

我自己使用了Realm's strip-frameworks.sh,它完美地为我工作而没有任何修改,当然任何人都可以自由地从头开始写一个.


我建议阅读的主题链接,因为它包含了这个问题的另一个方面:代码签名 - 创建iOS/OSX框架:是否有必要在分发给其他开发人员之前对其进行编码

  • 我在2016年12月没有发现任何Xcode 8.2改变的证据.:/ (2认同)

sky*_*der 56

这不是那么明确的解决方案,但只有办法,我发现:

  1. 设置ONLY_ACTIVE_ARCH=NOBuild Settings

    • 为模拟器构建库
    • 为设备构建库
  2. Products框架的控制台文件夹中 打开(可以通过打开框架文件夹打开它,然后cd ..从那里打开)

在此输入图像描述 在此输入图像描述

  1. 从文件夹运行脚本Products.它在此文件夹中创建fat Framework.(或按照下面第3章中的说明手动完成.4.)

要么:

  1. 通过此脚本使用lipo组合这两个框架(替换YourFrameworkName为您的框架名称)

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
    
    Run Code Online (Sandbox Code Playgroud)
  2. 替换为现有框架的新二进制文件:

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
    mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
    
    Run Code Online (Sandbox Code Playgroud)

  1. 利润:./YourFrameworkName.framework- 是现成的胖二进制!您可以将其导入您的项目!

对于项目,不在工作区中:

您也可以尝试使用此处所述的要点.但似乎它不适用于工作空间中的项目.


odm*_*odm 10

@Stainlav的答案非常有用,但我做的是编译框架的两个版本(一个用于设备,一个用于模拟器),然后添加以下内容Run Script Phase以自动复制运行架构所需的预编译框架

echo "Copying frameworks for architecture: $CURRENT_ARCH"
if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then
  cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
  cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi
Run Code Online (Sandbox Code Playgroud)

这样我就无法lipo创建一个胖框架,也不会strip-frameworks.sh在提交到App Store时删除不必要的切片.

  • 爱它!这比组合 - 撕裂 - "脂肪"方法简单得多. (2认同)