一、生成部分
參考: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
因為庫用到了第三方庫,而使用庫的項目沒有。把需要的第三方庫添加進來