代码改变世界

Xcode10 创建 framework (Objective-c),bundle(包含xib、image),第三方库,使用报错

2018-11-06 19:42  法子  阅读(2741)  评论(0编辑  收藏  举报

一、生成部分

参考:http://www.cocoachina.com/ios/20150127/11022.html

https://www.jianshu.com/p/87dbf57cfe4a (里面的脚本有问题,我参考另一篇文章做了修改)

https://www.jianshu.com/p/ef3d5b7e7006?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=qq

https://ask.csdn.net/questions/701924

1.打开Xcode,新建Project。类型:Cocoa Touch Framework,language:Objective-c。

生成项目后记得把Deployment Target调到需要的最低支持的iOS版本

2.随便建建一个类Converter,写一个HelloWorld函数。

Converter.h里声明函数

+(void)helloWorld;

 Converter.m里实现函数

+(void)helloWorld {
    NSLog(@"Hello World");
}

并且在LYFHelloWorld.h(建工程时候系统自动生成的)里声明所有要公开的头文件,以便将来使用这个库时可以引用

 3.·将你要公开的头文件移动到Public下,要隐藏的放在Private或者Project下

·如果有xib和图片资源,不要把它们加到Copy Bundle Resource里。(如果已经加了,就移除,因为就算添加了也无法使用。)

因为后面会把它们整合到一个LYFHelloWorldResource.bundle里,所以先提前修改所有使用image和xib的代码,在名字前加将要创建的bundle的名字:"LYFHelloWorldResource.bundle/"。如果xib里面用到了图片,把图片名字前也加上"LYFHelloWorldResource.bundle/",这样会导致图片不显示,但是另一个项目使用这个framework时候路径是对的。

//因为后面会把资源放到LYFHelloWorldResource.bundle里
//[UIImage imageNamed:@"IMG_0799.jpg"],就算图片在Assets.xcassets里,图片名要带后缀例如".jpg",因为要把Assets.xcassets里的图片都移到bundle里。
[UIImage imageNamed:@"LYFHelloWorldResource.bundle/IMG_0799.jpg"]
// [[NSBundle mainBundle] loadNibNamed:@"LYFShowView" owner:self options:nil].firstObject
[[NSBundle mainBundle] loadNibNamed:@"LYFHelloWorldResource.bundle/LYFShowView" owner:self options:nil].firstObject

 

4.修改配置。

前两个自己不理解(https://my.oschina.net/Jerod/blog/756465),试验了一下没什么大问题,所以没做修改。

第三个不改的话,别人用你的库会闪退报错:Reason: image not found

5.增加armv7s。(如果不需要支持iPhone5,5C,就可以跳过这一步)

    • arm7: 在最老的支持iOS7的设备上使用

    • arm7s: 在iPhone5和5C上使用

    • arm64: 运行于iPhone5S的64位 ARM 处理器 上

    • i386: 32位模拟器上使用

    • x86_64: 64为模拟器上使用

8.选择需要编译release或debug

这时候

选中模拟器编译,可以生成可在模拟器中用的库,(如果在终端lipo -info  ....../LYFHelloWorld.framework/LYFHelloWorld,结果是: x86_64)

选中Generic iOS Device编译,可以生产可在真机中使用的库,(如果 lipo -info 这个,结果是:armv7 arm64 armv7s)

如果要生成模拟器和真机都可以用的库,(即lipo -info结果是:i386 armv7 armv7s x86_64 arm64)。

有两种办法

(1)·命令行合并两个库

#lipo -create 模拟器库 真机库  -output 新地址/库名
lipo -create /Users/yongfaliu/Library/Developer/Xcode/DerivedData/LYFHelloWorld-cwlpmormfoqzfvctlyefrysrtqux/Build/Products/Debug-iphonesimulator/LYFHelloWorld.framework/LYFHelloWorld /Users/yongfaliu/Library/Developer/Xcode/DerivedData/LYFHelloWorld-cwlpmormfoqzfvctlyefrysrtqux/Build/Products/Debug-iphoneos/LYFHelloWorld.framework/LYFHelloWorld -output /Users/yongfaliu/Desktop/new/LYFHelloWorld

 

·用生产的新库替换原来的任何一个。被替换二进制文件的FrameWork就同时可以在模拟器和真机上使用

(2).在Xcode内完成

·新建Aggregate

·为新建的Target添加脚本

·很早以前的脚本在新环境下最后生成的库大小为0kb,这是新的。

#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products/"

#创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"

#分别编译模拟器和真机的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

#拷贝framework到univer目录
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"

#合并framework,输出最终的framework到build目录
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"

#删除编译之后生成的无关的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done

#判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi

rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"

#打开合并后的文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"

·然后Edite Scheme里选择需要编译release或debug,选最新的Target编译,新的库最后会在弹出的Finder里

9.将库拖到新的工程里就可以使用。当然要声明头文件。

10.如果有代码里用到了image和xib文件,还要创建bundle文件。

·这里命名为"LYFHelloWorldResource.bundle"(第3步里提到过)。修改Deployment Target的最低支持iOS版本和选择release或debug。

·修改配置。第一个是因为bundle默认是macOS的,第二个不改编译会报错,第三个不改图片格式是tiff

·将image和xib添加到Copy Bundle Resource里,将Assets.xcassets里的图片拖出来直接放到到项目里,然后也添加到Copy Bundle Resource里面。

 

·选择bundle编译之后。像framework一样,拖到新工程里就可以了。

11.如果用到了第三方库,就最好用pod管理。像正常项目一样,初始化pod,添加第三方库,然后编译出framework。使用这个framework的新项目也要在pod中添加相同的第三方库。这样两边都能够正常运行。

二、使用报错

参考:https://blog.csdn.net/u012243474/article/details/52619344

https://www.jianshu.com/p/0e2f6afa43dd

https://developer.apple.com/library/archive/qa/qa1490/_index.html

1.使用库的时候报:Reason: image not found

将生成库的target里的Build Settings里的Mach-O Type修改为Static Library,重新生成库

2.使用库的时候报:unrecognized selector sent to

因为库里有分类,使用库的时候,调用分类的方法就会这样报错,要修改使用库的项目的链接配置。

(1)如果只有分类,把Build Settings里的Other Linker Flags修改为-ObjC;

(2)如果库里同时有类和分类,把Build Settings里的Other Linker Flags修改为:(第二个可以把库拖进去,再添加"/库名")

-force_load

 $(SRCROOT)/XXXXX/framework/Debug/XXXXX.framework/XXXXX

3.使用库的时候,编译报:ld: symbol(s) not found for architecture

因为库用到了第三方库,而使用库的项目没有。把需要的第三方库添加进来