iOS Framework
Framework相比于动态/静态库,有如下优势:
- framework能将不同类型的资源打包在一起,包括nib文件、图片或者文档等;
- framework能够进行版本管理,这使得framework能不断更新并向后兼容;
- 节省内存,系统在需要的时候把framework载入内存,在同一时间,即使有多个应用程序使用同一 framework,但在内存中只有一份 framework 只读资源的拷贝,这减少了对内存的占用。
由于Xcdoe没有提供Framework的生成模板,Framework的生成需要依靠自己由Library的模板修改制作或者直接利用别人提供的模板。
Framework模板
推荐一个比较成熟的模板:https://github.com/kstenerud/iOS-Universal-Framework
安装模板
1.下载上述模板之后解压,在Real Framework目录下找到install.sh,打开终端,把文件拖进去,回车运行。
2.提示Xcode的安装路径
Where is Xcode installed? (CTRL-C to abort) [ /Applications/Xcode.app/Contents/Developer ]:
这是默认安装路径,如果Xcode在这里继续回车。
3.然后提示模板的安装位置
The templates will be installed in /Users/user/Library/Developer/Xcode/Templates/Framework & Library
continue [y/N]:
输入y,回车,然后输入管理员密码,回车,即安装成功。
4.打开Xcode,新建工程的时候,IOS下Framework&Library中就会多一个模板(Static iOS Framework),选择Framework新建工程。
5.在Framework中加入相关代码。
6.设置外部头文件:选择Target,Build Phases->Copy Headers。在点击+号选择头文件到Project下,然后邮件选择该头文件可以选择移动到Public或者Private选择项下。放到Public下面的头文件在Framework生成时存放在Header里,可以被直接引用。
7.在Device和Simulator模式下编译工程或分别在DerivedData/***/Build/Products目录下分别生成Debug-iphoneos和Debug-iphonesimulator目录,目录里面是分别对用的ARM和i386框架下的.framework文件包。终端使用lipo -info /Users/…/Debug-iphonesimulator/TestFrame.framework/TestFrame可以查看其框架属性。
8.使用命令生成模式通用的Framework:
lipo -create /Users/…/Debug-iphonesimulator/TestFrame.framework/TestFrame Users/…/Debug-iphoneos/TestFrame.framework/TestFrame -output /Users/user/Desktop/TestFrame
然后把生成的TestFrame拷贝到真机或者模拟器下任意一个.framework目录下,然后该.framework文件即为通用的Framework,可以引用使用。
参考文档:http://sishuok.com/forum/blogPost/list/6217.html
手工制作Framework
手动制作Framwork由于没有模板可以直接创建,需要配置的内容较多,本人没有尝试。
参考链接:http://blog.sina.com.cn/s/blog_43a2eee70101affo.html
Framework的引用
引用Framework很简单:
1.把.framwork文件放到项目工程目录下。
2.打开目标工程,Target设置->Link Binary With Libraries->Add Others,在目中找到.framework文件,添加即可。添加完成之后项目目录的Framework目录下会增加新增的Framework,可以在此处查看Framework的外部头文件。
3.framework中文件的引用需要使用尖括号<>,例如#import <TestFrame/TestFrame.h>
4.如果Framwork中包含分类,需要在Build Settings/Other Linker Flags中加入:-ObjC
UniversalFramework制作脚本
生成通用二进制Framework需要lipo,一个命令行工具,它允许在通用文件上执行操作(类似于创建通用二进制, 列出通用文件内容等等)。本教程中使用lipo的目的是联合不同架构的二进制文件到单个输出文件中。你可以直接在命令行中使用lipo命令,但在本教程中你可以让Xcode执行一段创建通用库的命令行脚本来为你做这件事。
Xcode中一个集合目标可以一次构建多个目标,包括命令行脚本。在选中lib工程文件,点击+号增加新的Target,选择iOS/Other并点击Aggregate,如下图:
将目标命名为UniversalFramework,确保选中你的lib工程中。然后选择UniversalFramework Target。切换到Build Phases标签;点击+号增加Add Run Script Build Phase,如下图:
现在你需要设置脚本项。展开Run Script模块,在Shell行下粘贴如下代码:
# Sets the target folders and the final framework product.
FMK_NAME=ProjectName
FMK_VERSION=1
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
# Creates and renews the final product folder.
mkdir -p "${INSTALL_DIR}"
mkdir -p "${INSTALL_DIR}/Versions"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers"
# Creates the internal links.
# It MUST uses relative path, otherwise will not work when the folder is copied/moved.
ln -s "${FMK_VERSION}" "${INSTALL_DIR}/Versions/Current"
ln -s "Versions/Current/Headers" "${INSTALL_DIR}/Headers"
ln -s "Versions/Current/Resources" "${INSTALL_DIR}/Resources"
ln -s "Versions/Current/${FMK_NAME}" "${INSTALL_DIR}/${FMK_NAME}"
# Copies the headers and resources files to the final product folder.
cp -R "${DEVICE_DIR}/Headers/" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/"
# Removes the binary and header from the resources folder.
rm -r "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/Headers" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/${FMK_NAME}"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}"
rm -r “${WRK_DIR}"
Copy使用时修改最上面的工程名定义FMK_NAME和版本号定义FMK_VERSION的值。
以上脚本的含义:
1.设置宏定义,设置工程名称及Framede版本号
2.设置Framework的输出路径为当前项目的根路径下Products目录
3.设置在DerivedData/项目名/Build目录下创建的framework真机和模拟器版本的存放目录
4.设置Xcode运行Frame工程师时编译Release版的真机和模拟器两种版本。
5.删除以前输出的Framework目录
6.创建新的Framework目录及其内容
7.创建Framework内目录间的关联关系
8.复制真机版本Framwork目录中的头文件和资源文件到输出的Framework中
9.删除无用资源及文件
10.使用lipo命令生成通用版的Framework并放到输出路径中。
设置完成之后,选择Target为UniversalFramework,编译,通过之后就在工程根目录多出一个Products目录,它包含四个文件目录:Headers、Resources、Versions、Frame文件,终端使用lipo -info Frame文件目录即可查看该文件属性已经为通用i386和ARM的了。该Products下的***.framework已经是通用的Framework了。
Build Settings/Other Linker Flags说明:
- -all_load Loads all members of static archive libraries.
- -ObjC Loads all members of static archive libraries that implement an Objective-C class or category.
- -force_load (path_to_archive) Loads all members of the specified static archive library. Note: -all_load forces all members of all archives to be loaded. This option allows you to target a specific archive.