引言
SDK定义上是指软件开发包,对应iOS端来说就包含了库文件、头文件、资源文件等文件的集合。SDK开发就是在保证sdk源代码安全的情况,给开发者一个可方便快速接入的,兼容多个iOS系统、便于真机模拟器调试、可以上线AppStore的库。这句话包含的几个重要的信息将在本文中逐步详解。
Step1:设置building setting(选static或者dynamic)
Step2: 接口设计
- 接口命名的正确方式:createGroupWithTitle:(NSString *)title
包含:action(create)+parameters(title)
需要对参数类型进行校验:最好的错误回调应该是至少包含错误码,最好包含错误描述(中英文两种),如下面例子:(实例中包含错误码和错误简单描述、详细描述。)
-(void)requestGroupMasterViaGroupId:(NSString *)groupId
requestSucess:(RequestGroupMasterSucess)success
requestError:(RequestGroupMasterError) error;
typedef void (^RequestGroupMasterError) (CMIMError * error);//获取群主详情失败回调
//回调的参数是一个CMIMError实例:
@interface CMIMError : NSObject
@property (nonatomic, assign) CMIMErrorCode code;
@property (nonatomic, readwrite, copy) NSString *codeDescription;
@property (nonatomic, readwrite, copy) NSString *detailDescription;
+ (instancetype)errorWithCode:(CMIMErrorCode)aCode;
- (instancetype)initWithCode:(CMIMErrorCode)aCode;
category、第三方库、类的命名、宏定义命名需要独一无二
头文件、属性暴露合理
保证代码安全就是保证头文件暴露合理,并且头文件中只暴露开发者需要用到的属性(定义好readonly属性)和接口,这样可以保证开发者不会错误调用其他接口或属性使SDK内部状态或逻辑错乱。支持的最低系统
通过app可能根据用户群体有不同的最低系统支持,例如目前很多app已经不再支持ios8以下系统,但是SDK作为app的内核,需要保证不同客户的需求都能满足,所以SDK应该尽可能保证支持最低系统,一般到iOS6.支持模拟器调试
为了便于开发者调试,需要支持模拟器调试,所以在打包framework时需要有x86和i386版本,并通过lipo指令将二者合并到armv7 v7s arm64中去。
步骤:
- 新建一个framework
- 参数配置
- Build Settings >> Dead Code Stripping >> 设置为NO
- Build Settings >> Strip Debug Symbol During Copy >> 全部设置为NO
- Build Settings >> Strip Style >> 设置为Non-Global Symbols
- Build Settings >> Link With Standard Libraries >> 设置为 NO
- Build Settings >> Mach-O Type >> Static Library
- 对于Mach-O Type:选择 Static Library 打出来的是静态库
- 设置头文件的属性(public/project)
- 设置debug和release的地址
- 编译
- 复制合并
实例
步骤:
新建一个工程名称为“ProjectName”,类型为:Cocoa Touch Static Library
删除与工程名相同的ProjectName.m文件
在ProjectName.h文件中,将所有内容删除,增加:#import < UIKit/UIKit.h>
将UIKit作为依赖库,加入到工程中(点击BuildPhases,展开Link Binary with Libraries这一部分,点击+添加一个新的framework,找到UIKit.framework,点击add添加进来)
在BuildPhases中,点击“new Headers Phase”
将公开的头文件,拖到Public下,将私有的头文件,拖到projcet下
新建一个文件夹,命名为:”folder”,将公共的头文件,放到folder文件夹下
在“Build Setting”中,搜索“public header”,设置Public Headers Folder Path为:include/$(PROJECT_NAME)/folder
进行简化设置(无效代码和debug用符号)
- Dead Code Stripping设置为NO
- Strip Debug Symbol During Copy 全部设置为NO
- Strip Style设置为Non-Global Symbols
- 编译运行
11.创建framework- Build Phases栏,选择Editor/Add Build Phase/Add Run Script Build Phase来添加一个新的脚本
set -e
export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"
# Create the path to the real Headers dir
mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"
# Create the required symlinks
/bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"
/bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"
/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \
"${FRAMEWORK_LOCN}/${PRODUCT_NAME}"
# Copy the public headers into the framework
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
"${FRAMEWORK_LOCN}/Versions/A/Headers"
- 选择静态库,编译
12 创建Aggregate ,命名为“Framework”
13 将静态库,添加到Aggregate中
14 添加脚本信息
set -e
# If we're already inside this script then die
if [ -n "$RW_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then
exit 0
fi
export RW_MULTIPLATFORM_BUILD_IN_PROGRESS=1
RW_FRAMEWORK_NAME=${PROJECT_NAME}
RW_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"
RW_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework"
function build_static_library {
# Will rebuild the static library as specified
# build_static_library sdk
xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \
-target "${TARGET_NAME}" \
-configuration "${CONFIGURATION}" \
-sdk "${1}" \
ONLY_ACTIVE_ARCH=NO \
BUILD_DIR="${BUILD_DIR}" \
OBJROOT="${OBJROOT}" \
BUILD_ROOT="${BUILD_ROOT}" \
SYMROOT="${SYMROOT}" $ACTION
}
function make_fat_library {
# Will smash 2 static libs together
# make_fat_library in1 in2 out
xcrun lipo -create "${1}" "${2}" -output "${3}"
}
# 1 - Extract the platform (iphoneos/iphonesimulator) from the SDK name
if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
RW_SDK_PLATFORM=${BASH_REMATCH[1]}
else
echo "Could not find platform name from SDK_NAME: $SDK_NAME"
exit 1
fi
# 2 - Extract the version from the SDK
if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then
RW_SDK_VERSION=${BASH_REMATCH[1]}
else
echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
exit 1
fi
# 3 - Determine the other platform
if [ "$RW_SDK_PLATFORM" == "iphoneos" ]; then
RW_OTHER_PLATFORM=iphonesimulator
else
RW_OTHER_PLATFORM=iphoneos
fi
# 4 - Find the build directory
if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$RW_SDK_PLATFORM$ ]]; then
RW_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${RW_OTHER_PLATFORM}"
else
echo "Could not find other platform build directory."
exit 1
fi
# Build the other platform.
build_static_library "${RW_OTHER_PLATFORM}${RW_SDK_VERSION}"
# If we're currently building for iphonesimulator, then need to rebuild
# to ensure that we get both i386 and x86_64
if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then
build_static_library "${SDK_NAME}"
fi
# Join the 2 static libs into 1 and push into the .framework
make_fat_library "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
"${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \
"${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}"
# Ensure that the framework is present in both platform's build directories
cp -a "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}" \
"${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework/Versions/A/${RW_FRAMEWORK_NAME}"
# Copy the framework to the user's desktop
ditto "${RW_FRAMEWORK_LOCATION}" "${HOME}/Desktop/${RW_FRAMEWORK_NAME}.framework"
15 编译,桌面上会生成一个.Framework文件
16 在cmd中检查Framework文件
- $ cd ~/Desktop/projectName.Framework
- $ xcrun lipo -info projectName