用 Xcode 7 建立依赖其它第三方库静态库
编写 SDK 的时候, 经常会用到一些常用组件, 比如 AFNetworking.
如果直接将AFNetworking编译进 SDK ,那么如果用户在使用你写的 SDK 的同时也使用了 AFNetworking,那么会出现"duplicate symbol _OBJC_CLASS_$_xxx"的问题.
如果自己重新写一个功能类似 AFNetworking 的组件,一来是很麻烦,二来像这种成熟的第三方库, 都是经过很多人测试过,多次修改 bug的,自己写的话,未必比得上,而且重复造轮子也是没有多大意义的.
接下来我们就来开始写一个简单的 SDK,并且使用 AFNetworking库
今天的任务是编写一个快递查询 SDK, 使用的是快递100 的API, API 信息源自 BeJSON
-
创建工程
选择模板
与创建其他工程唯一区别是选择模板的时候要选Cocoa Touch Framework,后面就没什么区别了
至于为何不选择 Cocoa Touch Static Library 是因为虽然后者也能建立静态库,但是最后得到的是一堆头文件加上一个 .a 文件,不容易部署, 而 Framework 则是把头文件和编译好的二进制文件打包为一个. framwork ,容易部署. -
加入 AFNetworking
既然要使用 AFNetworking ,自然要先引入, 我用 CocoaPods 来管理, 至于你如果问我没用过 CocoaPods,有没有别的办法? 我还真不知道, 我觉得要是直接把源文件放到工程中多半是不行的, 如果不会可以学习一下 CocoaPods 的使用方法,参见这位大神的文章.
新建一个 Podfile, 内容如下, 推介使用Xcode 插件,比如CocoaPods 插件
platform :ios, '7.0'
target 'ExpressInfo' do
pod 'AFNetworking'
end
ExpressInfo 是我的项目名,你可以改成你自己的名字.记得加上 target 'xxx' do ... end, 要不然后面编译要提示can't locate file for: -lPods 错误.
用命令或是插件执行安装.接下来就可以愉快的使用AFNetworking 了.
-
编写 SDK
引入所有公开头文件
源码在这里 GitHub
注意一点
ExpressInfo.h,这个文件中,要把所有需要公开的头文件全部列举出来
-
配置
打开SDK 这个 target 的 build phase ,找到 Headers, 将 project 中需要公开的头文件选中,移动到 public group 中
设置头文件
接下来到 General 中设置需要支持的版本, Build Setting 中加入 armv7s
添加 armv7s
既然我们是编写的静态库,就需要将 Mach-O Type 设置为 Static Library
设置为静态库
接下来可以编译试试有没有什么错误和警告
如果没有,就可以进行下一步了
-
增加合并模拟器和真机的 Aggregate Target
由于编译的时候,只会编译当前选中设备的版本,为了编译一份同时能够运行于真机和模拟器的 SDK ,我们再增加一个 target
Aggregate Target
在这个 Target 里面选择 Build Phase, 新建一个 Run Script
添加 Run Sctipt
代码如下
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
WORKSPACE_NAME=${PROJECT_NAME}.xcworkspace
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -workspace "${WORKSPACE_NAME}" -scheme "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphoneos ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -workspace "${WORKSPACE_NAME}" -scheme "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
fi
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
run script
设置这个 Target 为 Release
设置为 Release
接下来可以切换到这个 Target 编译了,完成之后,会自动弹出 Framework 所在的文件夹
编译好的文件
- 小试牛刀
接下来实际使用一下这个 SDK - 先创建一个普通的项目
- 添加刚才创建的 Framework
添加 Framework 到项目
3.接下来可以编写代码了, 我的源代码在这里GitHub
编写源代码 -
由于我们的 SDK 使用了 AFNetworking, 而 AFNetworking 是没有编译进入我们 SDK 的. 如果直接编译, 会出现找不到类的错误
错误
所以使用的时候, 需要加上AFNetworking, 使用 CocoaPods 或者直接使用源文件都可以.
5.现在可以运行试试了
运行测试
打完收工. 若有任何指教, 欢迎留言