Xcode10 创建 framework (Objective-c),bundle(包含xib、image),第三方库,使用报错
2018-11-06 19:42 法子 阅读(2768) 评论(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
因为库用到了第三方库,而使用库的项目没有。把需要的第三方库添加进来