【Objective-c】开发封装动态库framework 装B神技

开发中我们也经常会使用第三方SDK,只要几行代码就实现功能,重点是你看不到代码是怎么实现的,顿时感觉这个逼格很高,大牛一位。(面试中甚至有面试官问:你会不会封装SDK?当时心中忐忑不安,心想什么鬼,面试的是多少K的工作,居然要会SDK)

普及一下静态库和动态库的定义及区别

静态库即静态链接库(Windows 下的 .lib,Linux 和 Mac 下的 .a)。之所以叫做静态,是因为静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。静态库的好处很明显,编译完成之后,库文件实际上就没有作用了。目标程序没有外部依赖,直接就可以运行。当然其缺点也很明显,就是会使用目标程序的体积增大。

动态库动态库即动态链接库(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib)。与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。动态库的优点是,不需要拷贝到目标程序中,不会影响目标程序的体积,而且同一份库可以被多个程序使用(因为这个原因,动态库也被称作共享库)。同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码。动态库带来的问题主要是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行(Linux 下喜闻乐见的 lib not found 错误)。

创建动态库framework的步骤》》》》》》见图

1、新建项目


Snip20161019_1.png

2、将代码导入到项目中,并将公开的接口暴露


Snip20161019_2.png

注意:开放接口的头文件,一定要导入这个新建文件的头文件中,否则其他项目导入framework时会出现:找不到子模块的警告⚠️
Snip20161019_12.png

3、设置适合所有框架


Snip20161019_3.png

4、因为动态库打包出来只能是在真机或模拟器使用,为了方便调试,可以添加一个脚本命令,生成一个同时支持真机和模拟机的framework


![Snip20161019_5.png](http://upload-images.jianshu.io/upload_images/1923392-73cdcf4be0b4b5e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Snip20161019_6.png

Snip20161019_7.png

脚本命令
set
 -e

set
 +u

### Avoid recursively calling this script.

if
 [[ $UF_MASTER_SCRIPT_RUNNING ]]

then

exit 0

fi

set
 -u

export UF_MASTER_SCRIPT_RUNNING=1

### Constants.

UF_TARGET_NAME=${PROJECT_NAME}

FRAMEWORK_VERSION=
"A"

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

IPHONE_SIMULATOR_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator

### Functions

## List files in the specified directory, storing to the specified array.

#

# @param $1 The path to list

# @param $2 The name of the array to fill

#

##

list_files ()

{

filelist=$(ls 
"$1"
)

while
 read line

do

eval 
"$2[\${#$2[*]}]=\"\$line\""

done <<< 
"$filelist"

}

### Take build target.

if
 [[ 
"$SDK_NAME"
 =~ ([A-Za-z]+) ]]

then

SF_SDK_PLATFORM=${BASH_REMATCH[1]} # 
"iphoneos"
 or 
"iphonesimulator"
.

else

echo 
"Could not find platform name from SDK_NAME: $SDK_NAME"

exit 1

fi

### Build simulator platform. (i386, x86_64)

echo 
"========== Build Simulator Platform =========="

echo 
"===== Build Simulator Platform: i386 ====="

xcodebuild -project 
"${PROJECT_FILE_PATH}"
 -target 
"${TARGET_NAME}"
 -configuration 
"${CONFIGURATION}"
 -sdk iphonesimulator BUILD_DIR=
"${BUILD_DIR}"
 OBJROOT=
"${OBJROOT}"
 BUILD_ROOT=
"${BUILD_ROOT}"
 CONFIGURATION_BUILD_DIR=
"${IPHONE_SIMULATOR_BUILD_DIR}/i386"
 SYMROOT=
"${SYMROOT}"
 ARCHS=
'i386'
 VALID_ARCHS=
'i386'
 $ACTION

echo 
"===== Build Simulator Platform: x86_64 ====="

xcodebuild -project 
"${PROJECT_FILE_PATH}"
 -target 
"${TARGET_NAME}"
 -configuration 
"${CONFIGURATION}"
 -sdk iphonesimulator BUILD_DIR=
"${BUILD_DIR}"
 OBJROOT=
"${OBJROOT}"
 BUILD_ROOT=
"${BUILD_ROOT}"
 CONFIGURATION_BUILD_DIR=
"${IPHONE_SIMULATOR_BUILD_DIR}/x86_64"
 SYMROOT=
"${SYMROOT}"
 ARCHS=
'x86_64'
 VALID_ARCHS=
'x86_64'
 $ACTION

### Build device platform. (armv7, arm64)

echo 
"========== Build Device Platform =========="

echo 
"===== Build Device Platform: armv7 ====="

xcodebuild -project 
"${PROJECT_FILE_PATH}"
 -target 
"${TARGET_NAME}"
 -configuration 
"${CONFIGURATION}"
 -sdk iphoneos BUILD_DIR=
"${BUILD_DIR}"
 OBJROOT=
"${OBJROOT}"
 BUILD_ROOT=
"${BUILD_ROOT}"
  CONFIGURATION_BUILD_DIR=
"${IPHONE_DEVICE_BUILD_DIR}/armv7"
 SYMROOT=
"${SYMROOT}"
 ARCHS=
'armv7 armv7s'
 VALID_ARCHS=
'armv7 armv7s'
 $ACTION

echo 
"===== Build Device Platform: arm64 ====="

xcodebuild -project 
"${PROJECT_FILE_PATH}"
 -target 
"${TARGET_NAME}"
 -configuration 
"${CONFIGURATION}"
 -sdk iphoneos BUILD_DIR=
"${BUILD_DIR}"
 OBJROOT=
"${OBJROOT}"
 BUILD_ROOT=
"${BUILD_ROOT}"
 CONFIGURATION_BUILD_DIR=
"${IPHONE_DEVICE_BUILD_DIR}/arm64"
 SYMROOT=
"${SYMROOT}"
 ARCHS=
'arm64'
 VALID_ARCHS=
'arm64'
 $ACTION

### Build device platform. (arm64, armv7)

echo 
"========== Build Universal Platform =========="

## Copy the framework structure to the universal folder (clean it first).

rm -rf 
"${UNIVERSAL_OUTPUTFOLDER}"

mkdir -p 
"${UNIVERSAL_OUTPUTFOLDER}"

## Copy the last product files of xcodebuild command.

cp -R 
"${IPHONE_DEVICE_BUILD_DIR}/arm64/${PROJECT_NAME}.framework"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"

### Smash them together to combine all architectures.

lipo -create  
"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/i386/${PROJECT_NAME}.framework/${PROJECT_NAME}"
 "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/x86_64/${PROJECT_NAME}.framework/${PROJECT_NAME}"
 "${BUILD_DIR}/${CONFIGURATION}-iphoneos/armv7/${PROJECT_NAME}.framework/${PROJECT_NAME}"
 "${BUILD_DIR}/${CONFIGURATION}-iphoneos/arm64/${PROJECT_NAME}.framework/${PROJECT_NAME}"
 -output 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

### Create standard structure for framework.

#

# If we don't have "Info.plist -> Versions/Current/Resources/Info.plist", we may get error when use this framework.

#

# MyFramework.framework

# |-- MyFramework -> Versions/Current/MyFramework

# |-- Headers -> Versions/Current/Headers

# |-- Resources -> Versions/Current/Resources

# |-- Info.plist -> Versions/Current/Resources/Info.plist

# `-- Versions

#     |-- A

#     |   |-- MyFramework

#     |   |-- Headers

#     |   |   `-- MyFramework.h

#     |   `-- Resources

#     |       |-- Info.plist

#     |       |-- MyViewController.nib

#     |       `-- en.lproj

#     |           `-- InfoPlist.strings

#     `-- Current -> A

#

echo 
"========== Create Standard Structure =========="

mkdir -p 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/"

mv 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/"

mv 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Headers"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/"

mkdir -p 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources"

declare -a UF_FILE_LIST

list_files 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/"
 UF_FILE_LIST

for
 file_name 
in
 "${UF_FILE_LIST[@]}"

do

if
 [[ 
"${file_name}"
 == 
"Info.plist"
 ]] || [[ 
"${file_name}"
 =~ .*\.lproj$ ]]

then

mv 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${file_name}"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources/"

fi

done

mv 
"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/${FRAMEWORK_VERSION}/"

ln -sfh 
"Versions/Current/Resources/Info.plist"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Info.plist"

ln -sfh 
"${FRAMEWORK_VERSION}"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Versions/Current"

ln -sfh 
"Versions/Current/${PROJECT_NAME}"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

ln -sfh 
"Versions/Current/Headers"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Headers"

ln -sfh 
"Versions/Current/Resources"
 "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Resources"

### Open the universal folder.

open 
"${UNIVERSAL_OUTPUTFOLDER}"

5、生成framework文件,选中“StyleBox”文件,运行程序


Snip20161019_9.png

Snip20161019_11.png

到这里,framework的创建已经成功了,只要右击“show in Finder”,就可以找得framework并导入其他项目中

Paste_Image.png

项目实际使用中,直接导入framework,并且需要动态库需要在此添加:


Snip20161019_14.png

当动态库中,包含资源文件如nib文件或图片的....


Snip20161019_13.png

以上是创建framework的基本流程

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

推荐阅读更多精彩内容