iOS制作framework

转载请注明出处:

http://www.jianshu.com/p/04a7e28f11b9

作者:纪小衰

framework的使用十分方便,一般来说直接拖入到项目中就可以直接使用接口,而不用在意具体的实现细节,对于功能的封装是个很好的途径。当我们写的工具给别人使用的同时又不想让别人知道自己的代码,这个时候使用framework就可以派上用场了(ps:个人觉得开源是一个大牛必须要体会到的思想)。。。

废话不多说,xcode如今已经到了7,对于framework的制作可以说是十分方便了。公司之前的framework的制作都是采用执行纯脚本的方法,可以直接命令行编译和融合不同版本(模拟器,真机,debug,release)的framework,个人不是很喜欢,还是喜欢用较为官方的方式来制作framework,当然为了方便还是少量地参照了网上的一些脚本。

一、新建framework工程


xcode->file->new->project选中iOS下的cocoa touch framework->next

创建工程

接下来的步骤和创建一个普通的工程没什么区别,创建完毕以后在工程中新建JRModel类和JRModel2类文件,在我们的framework工程创建以后系统会默认创建一个和工程名相同的头文件,我这里是JRDataModel.h。一般来说我们会把framework中需要提供给外部的头文件都在这个头文件中import一下,这样使用者只要包含一个头文件就可以使用所有的类了。

创建文件后导入公共头文件

这个地方需要注意到两点,一个就是导入的时候必须要使用framework的方式导入,使用<包名/头文件名.h>,因为在实际使用framework的时候是需要从包中搜索头文件的。还有一个坑就是右边的那个设置,对于总的头文件还有所有需要用到的头文件,都需要公开,选中以后把右边包的编译属性改为public,否则打出来的包在别的工程中实际上是不能引用的。

二、编译工程


接下来就是开始编译工程了(如下图),选中运行按钮右边的编译目标,选择Generic iOS Device,然后command+b编译一下,这个时候我们工程中的products文件夹下面的framework文件会由原来的红色(表示文件丢失)变成黑色(表示文件存在)。如果我们选择的是Generic iOS Device那么编译出来的framework只能在真机中使用,如果选中的是普通的模拟器,那么编译出来framewo只能在模拟器中使用。

tips:这里需要注意一下,如果一开始选择的是模拟器,那么即使build成功,framework也不会变成黑色,可能是因为这里的framework指向的是真机中对应的framework,但是在相对应的目录下的模拟器对应的framework是存在的

编译framework

右击生成好的framework,选中show in finder可以查看framework在磁盘中的位置。进入目录以后,一般来说最多有四个目录,我这里只有三个(如下图)因为对于模拟器一般不会要release版本的。也可以通过finder,快捷键control+command+g输入~/Library/Developer/Xcode/DerivedData/Build/Products默认路径进入

分别在模拟器和真机选项中编译,发现实际只产生了模拟器和真机的debug版本的framework包,而没有release版本的包。这需要我们调整一下xcode的build类型,选中运行的target在下来列表中选Edit Scheme,进入以后把run中的Build Configureation修改为Release,这时候就可以编译出release版本的包了(如下图)

三、合并framework


到此,我们已经制作出对于各种情况下使用的framework了,对于不同的环境需要使用不同种类的framework,这在很多时候显得很麻烦。能不能制作一个能在所有场景使用的包呢。

这个时候我们可以考虑合并所有版本的包,一般来说可以使用脚本进行合并,但是每次使用脚本比较麻烦,我们可以在xcode中添加一个共同体aggregate,然后添加编译脚本来实现。

在工程中点击上方工具栏File->New->Target,在选项中选择Other中的Aggregate,命名最好和工程名有关,我这里就写成JRDataModelAggregate。

新建Aggregate

新建好以后,选择targets列表下的JRDataModelAggregate,点击build phases,点击+新建一个New Run Script Phase,把下面的脚本复制到shell下的选项中(脚本来源自网络,感谢这段脚本的原作者)。有能力的可以根据自己的需要修改下面的脚本。

# Sets the target folders and the final framework product.

#如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME

#例如: FMK_NAME = "MyFramework"

FMK_NAME=${PROJECT_NAME}

# 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

# -configuration ${CONFIGURATION}

# Clean and Building both architectures.

xcodebuild -configuration"Release"-target"${FMK_NAME}"-sdk iphoneos clean build

xcodebuild -configuration"Release"-target"${FMK_NAME}"-sdk iphonesimulator clean build

# Cleaning the oldest.

if [ -d"${INSTALL_DIR}"]

then

rm -rf"${INSTALL_DIR}"

fi

mkdir -p"${INSTALL_DIR}"

cp -R"${DEVICE_DIR}/""${INSTALL_DIR}/"

# 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}/${FMK_NAME}"

rm -r"${WRK_DIR}"

open"${INSTALL_DIR}"

粘贴shell脚本

复制完以后,点击左上角运行旁边的target(上图左上角那个黄色的选项),在下拉的列表中选中我们刚才创建的JRDataModelAggregate,command+B编译一下,如果没什么意外,等到编译成功便会弹出我们编译好的framework了。

四、验证framework


framework其实可以看做是一个带扩展名的文件夹,所以我们可以直接进入framework的内部。通过下面的控制台指令进入到framework中(cd后面是你自己的framework路径)

cd /Users/ctzxh/Desktop/JRModel/JRDataModel/Products/JRDataModel.framework

执行下面的命令判断当前framework支持的架构

lipo -info JRDataModel

完成验证

Tips1:

对于上面的每种处理器架构对应的设备请自行百度。这里说明一下,如果让你的包可以支持armv7s的架构(这里说的支持指的是针对这种架构的优化),可以根据下图的方式添加,新版的xcode默认便没有加上armv7s的架构,由于处理器向下兼容,所以即使不添加,所使用包的工程也是可以在armv7s架构上的机器运行的。个人推荐还是不必考虑了,按照官方的来就可以了。添加完以后在验证包的时候会多显示一个armv7s。

添加armv7s架构

Tips2:

上面用Aggregate制作的库是拖入到使用的工程是直接可以使用的,但是之前分别制作的库直接拖入是不能使用的,解决的方式有两种:

第一种:制作链接库的时候,选择生成静态库

第二种:在使用动态链接库的时候嵌入二进制库,在下面的选项中添加要导入的动态库

网上有种方式是把framework的属性从required变成Optional,亲测行不通,能导入但是不能用。。。

就到这儿吧~~~

Add:如果只做的是.a的静态库可以使用下面的脚本,方法一样

if["${ACTION}"="build"]

then

#要build的target名

target_Name=${PROJECT_NAME}

echo"target_Name=${target_Name}"

#build之后的文件夹路径

build_DIR=${SRCROOT}/build

echo"build_DIR=${build_DIR}"

#真机build生成的头文件的文件夹路径

DEVICE_DIR_INCLUDE=${build_DIR}/Release-iphoneos/include/${PROJECT_NAME}

echo"DEVICE_DIR_INCLUDE=${DEVICE_DIR_INCLUDE}"

#真机build生成的.a文件路径

DEVICE_DIR_A=${build_DIR}/Release-iphoneos/lib${PROJECT_NAME}.a

echo"DEVICE_DIR_A=${DEVICE_DIR_A}"

#模拟器build生成的.a文件路径

SIMULATOR_DIR_A=${build_DIR}/Release-iphonesimulator/lib${PROJECT_NAME}.a

echo"SIMULATOR_DIR_A=${SIMULATOR_DIR_A}"

#目标文件夹路径

INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}

echo"INSTALL_DIR=${INSTALL_DIR}"

#目标头文件文件夹路径

INSTALL_DIR_Headers=${SRCROOT}/Products/${PROJECT_NAME}/Headers

echo"INSTALL_DIR_Headers=${INSTALL_DIR_Headers}"

#目标.a路径

INSTALL_DIR_A=${SRCROOT}/Products/${PROJECT_NAME}/lib${PROJECT_NAME}.a

echo"INSTALL_DIR_A=${INSTALL_DIR_A}"

#判断build文件夹是否存在,存在则删除

if[ -d"${build_DIR}"]

then

rm -rf"${build_DIR}"

fi

#判断目标文件夹是否存在,存在则删除该文件夹

if[ -d"${INSTALL_DIR}"]

then

rm -rf"${INSTALL_DIR}"

fi

#创建目标文件夹

mkdir -p"${INSTALL_DIR}"

#build之前clean一下

xcodebuild -target${target_Name}clean

#模拟器build

xcodebuild -target${target_Name}-configuration Release -sdk iphonesimulator

#真机build

xcodebuild -target${target_Name}-configuration Release -sdk iphoneos

#复制头文件到目标文件夹

cp -R"${DEVICE_DIR_INCLUDE}""${INSTALL_DIR_Headers}"

#合成模拟器和真机.a包

lipo -create"${DEVICE_DIR_A}""${SIMULATOR_DIR_A}"-output"${INSTALL_DIR_A}"

#打开目标文件夹

open"${INSTALL_DIR}"

fi

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容