使用Embedded Framework(动态库)打包发布时遇到的错误,及解决方案

最近更新了一回工程中的第三方库,发现AFNetworking和环信在传统导入Framework时,一运行就crash。控制台打印日志显示:
dyld: Library not loaded: @rpath/AFNetworking.framework/AFNetworking Referenced from: /var/containers/Bundle/Application/66CDB081-574E-4B56-A2ED-DF78FB15526E/xxx.app/xxx Reason: image not found
  为什么先前没有碰到呢?Google之,发现AFNetworking新版本虽然形式依旧为Framework,但本质却改为动态库了。至于为什么要改为动态库,参照另一篇文章讲解。
  好了,知道了问题就要解决。从Xcode6开始就提供了两种导入Framework的方式,一种是很早就有的Linked Frameworks and Libraries,静态库导入,跟代码一起编译进二进制文件;另一种是Xcode6,也就是iOS8开始提供的Embedded Binaries嵌入动态库的形式。动态库嵌入后输出的.app包,Framework结构如下:

使用Embedded Framework(动态库)打包发布时遇到的错误,及解决方案_第1张图片
Archive生成包的动态库的结构

接下来,在整个开发过程中,都不再碰到Framework引发的问题。可就在提交App Store时,Xcode报了这个错:
ERROR ITMS-90087: "Unsupported Architecture. Your executable contains unsupported architecture '[x86_64, i386]'."
  按字面意思理解,是包里含有不支持的架构。x86_64和i386是模拟器架构,的确是在发布时不需要的。可是Framework是打好的包,如何去除是个问题。
  于是继续Google之,在stackoverflow上有人碰到了一样的问题,原文的正确答案里给出了一段编译脚本可解决问题,脚本最初来自于一位老外技术博客里的原创解决方案。对于这种写脚本解决问题的老外,我能说两个字,牛逼!脚本如下,按需自取:

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
    echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
    EXTRACTED_ARCHS=()
    for ARCH in $ARCHS
    do
        echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
        lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
        EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
    done
    echo "Merging extracted architectures: ${ARCHS}"
    lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
    rm "${EXTRACTED_ARCHS[@]}"
    echo "Replacing original executable with thinned version"
    rm "$FRAMEWORK_EXECUTABLE_PATH"
    mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done

大意就是,读取目标app目录,取到Framework目录,遍历之,取出Framework,对其瘦身。
  脚本添加后,可以指定在Archive时才使用,以免影响模拟器运行。

使用Embedded Framework(动态库)打包发布时遇到的错误,及解决方案_第2张图片
设置脚本仅在Archive时启用

你可能感兴趣的:(使用Embedded Framework(动态库)打包发布时遇到的错误,及解决方案)