基本概念
基本概念這里參照了奔狂的蝸牛_文章里的內(nèi)容蕾久。
什么是SDK
軟件開發(fā)工具包(縮寫:SDK冤荆,英語全稱:Software Development Kit),一般都是一些軟件工程師為特定的軟件包怨绣、軟件框架、硬件平臺哼御、操作系統(tǒng)等建立應(yīng)用軟件時的開發(fā)工具的集合民逼。
在OC的開發(fā)中霍殴,我們涉及到的一般是靜態(tài)庫(.a)或者動態(tài)庫(.framework)。(注:不是所有的.framework就一定是動態(tài)庫)
靜態(tài)庫與動態(tài)庫的區(qū)別帝簇?
靜態(tài)庫:鏈接時完整地拷貝至可執(zhí)行文件中徘郭,被多次使用就有多份冗余拷貝。表現(xiàn)形式為 .a和.framework己儒。動態(tài)庫:鏈接時不復(fù)制崎岂,程序運(yùn)行時由系統(tǒng)動態(tài)加載到內(nèi)存,供程序調(diào)用闪湾,系統(tǒng)只加載一次冲甘,多個程序共用,節(jié)省內(nèi)存途样。 表現(xiàn)形式為 .dylib和.framework江醇。注意:動態(tài)庫只能蘋果使用,如果項目中使用了動態(tài)庫不允許上架(如:jspatch)
a與.framework有什么區(qū)別何暇?
.a是一個純二進(jìn)制文件陶夜,.framework中除了有二進(jìn)制文件之外還有資源文件。 .a文件不能直接使用裆站,至少要有.h文件配合(微信的SDK就是這種形式)条辟,.framework文件可以直接使用。 .a + .h + sourceFile = .framework宏胯。 建議用.framework羽嫡。再者 靜態(tài)方式開發(fā),一直是iOS SDK開發(fā)的主流方式
一肩袍、準(zhǔn)備工作
1杭棵、創(chuàng)建一個目錄
用于將后面開發(fā)的文件統(tǒng)一管理在此目錄下。我這里命名為HLTestSDK-library
氛赐。
2魂爪、創(chuàng)建一個Workspace
放在HLTestSDK-library
目錄下。
用于管理SDK和SDK測試的工程艰管。這里命名為HLTestSDK-workspace
滓侍。
2.1、快捷鍵創(chuàng)建:control
+ command
+ n
2.2牲芋、手動創(chuàng)建如圖:
3撩笆、創(chuàng)建SDK工程也放在HLTestSDK-library
目錄下尔破。
命名為HLTestSDK
。
3.1浇衬、快捷鍵創(chuàng)建:shift
+ command
+ n
3.2懒构、手動創(chuàng)建如圖:
4.創(chuàng)建一個測試工程也放在HLTestSDK-library
目錄下。
用于測試SDK耘擂,命名為HLTestSDK-test
胆剧。
4.1、快捷鍵創(chuàng)建:shift
+ command
+ n
4.2醉冤、手動創(chuàng)建如圖:
至此我們準(zhǔn)備工作已經(jīng)做完秩霍。
查看
HLTestSDK-library
是否如下圖:查看
HLTestSDK-workspace.xcworkspace
是否如下圖:二、在HLTestSDK
中添加測試類
主要用于后面演示暴露頭文件和測試用蚁阳,如圖:
三铃绒、創(chuàng)建一個AggreGate文件關(guān)聯(lián)SDK
命名為HLTestSDK-aggregate
。
腳本內(nèi)容如下螺捐,可直接復(fù)制
#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}/"
#創(chuàng)建輸出目錄颠悬,并刪除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
#分別編譯模擬器和真機(jī)的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}"
lipo "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" -remove arm64 -output "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}"
#合并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}"
#刪除編譯之后生成的無關(guān)的配置文件
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}"
拷貝關(guān)聯(lián)后如圖:
四赔癌、配置SDK基礎(chǔ)設(shè)置及暴露給外部調(diào)用的頭文件
1.配置SDK支持最低版本
2.配置SDK支持設(shè)備
3.配置SDK為靜態(tài)庫(重點(diǎn))
4.配置
Enable Bitcode
5.配置SDK
Bulid Configuration
6.配置
Other Linker Flags
,添加-ObjC
7.配置
Build Active Architecture Only
設(shè)置為yes表示它只編譯當(dāng)前的architecture版本
設(shè)置為no表示會編譯所有的版本
為了提高編譯速度:
一般debug的時候可以選擇設(shè)置為yes澜沟,release的時候要改為no灾票,以適應(yīng)不同設(shè)備。
8.SDK暴露頭文件給第三方訪問
9.配置
Perform Single-Object Prelink
為YES
五茫虽、測試
如果控制臺打印了
Hello SDK
刊苍,表示你已入門SDK開發(fā)了!
六濒析、SDK項目中的資源文件Bundle(可選)
SDK開發(fā)過程中可能會使用到圖片等資源正什,這些資源我們需要使用Bundle來管理。
1悼枢、創(chuàng)建Bundle
最簡單的方式就是:在桌面上創(chuàng)建一個空的文件夾埠忘,然后文件名稱修改為.bundle
結(jié)尾脾拆,那么系統(tǒng)就把這個文件轉(zhuǎn)變成bundle文件馒索,然后拖入你的SDK項目中。
2名船、向Bundle中添加資源
選中Bundle文件
- 右鍵
- 顯示包內(nèi)容
- 將資源文件拖入即可
3绰上、SDK中使用資源
我們用圖片資源演示
/**
* 從Bundle中獲取圖片
* @param bundleName bundle名稱
* @param imageName 圖片名稱
*/
+ (UIImage *)imageWithBundle:(NSString *)bundleName imageName:(NSString *)imageName
{
if ([UIScreen mainScreen].scale == 3) {
imageName = [NSString stringWithFormat:@"%@@3x", imageName];
} else {
imageName = [NSString stringWithFormat:@"%@@2x", imageName];
}
// 靜態(tài)庫 url 的獲取
NSURL *url = [[NSBundle mainBundle] URLForResource:bundleName withExtension:@"bundle"];
if (!url) {
// 動態(tài)庫 url 的獲取
url = [[NSBundle bundleForClass:[self class]] URLForResource:bundleName withExtension:@"bundle"];
}
if (!url) {
return nil;
}
NSBundle *bundle = [NSBundle bundleWithURL:url];
UIImage *image = [UIImage imageNamed:imageName inBundle:bundle compatibleWithTraitCollection:nil];
return image;
}
七、SDK開發(fā)中其他擴(kuò)展(可選)
- 獲取當(dāng)前顯示的
ViewController
/**
* 獲取當(dāng)前顯示的 UIViewController
*/
+ (UIViewController *)findCurrentShowingViewController {
//獲得當(dāng)前活動窗口的根視圖
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];
return currentShowingVC;
}
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc
{
// 遞歸方法 Recursive method
UIViewController *currentShowingVC;
if ([vc presentedViewController]) {
// 當(dāng)前視圖是被presented出來的
UIViewController *nextRootVC = [vc presentedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UITabBarController class]]) {
// 根視圖為UITabBarController
UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UINavigationController class]]){
// 根視圖為UINavigationController
UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else {
// 根視圖為非導(dǎo)航類
currentShowingVC = vc;
}
return currentShowingVC;
}
-
Xcode13+: 工程目錄中沒有 products 路徑了
點(diǎn)擊頂部菜單Product > Show Build Folder in Finder
打開編譯后的路徑渠驼,Release-iphoneos 中的庫就是編譯后的庫文件蜈块。