iOS-Static Framework

  • 存放类的地方
  • 存放图片资源的地方
  • 打包生成的方式

第一步:创建一个新的"Cocoa Touch Static Library"工程

Static Library生成的是libSerenity.a的静态库文件.
而我们最终要生成的是Serenity.framework的方式.

效果图

创建:


创建

第二步:创建主框架的头文件

如果你希望其他开发者以<Serenity/Serenity.h> 的方式来使用你自己的静态库.那么你需要确保你的项目中包含该头文件.例如:

#import <Foundation/Foundation.h>
#import <Serenity/Widget.h>
(ps : Widget.h 是你项目中的其他文件)

一旦你创建了framew得头文件,你需要将这些头文件列为"public"的状态.

public

第三步 : 更新Public类型头文件的地址

默认情况下,静态库项目将私人的和public头文件复制在同一文件夹路径下: /usr/local/include. 为了避免错误的将私人标题复制到我们的框架,我们想确保我们的public头文件复制到一个单独的目录中. 例如 :$(PROJECT_NAME)Headers. 要去修改这些设定.

默认路径

编译后

编译后生成的头文件路径

修改后


修改后
$(PROJECT_NAME)Headers

再次编译


再次编译后的路径
接下来考虑: 添加一些新的资源到Framework

不管你什么时候要添加一些新的类,你将要考虑是否将这些.h文件是否置为public的状态,因为默认是Project的状态,默认不会拷贝到你刚刚创建的自定义的头文件路径.

测试

这里添加一个新的NewSource的类测试.
测试结果:

测试结果

第四步 : Disable Code Stripping

We do not want to strip any code from the library; we leave this up to the application that is linking to the framework. To disable code stripping we must modify the following configuration settings:

"Dead Code Stripping" => No             (for all settings)
"Strip Debug Symbols During Copy" => No (for all settings)
"Strip Style" => Non-Global Symbols     (for all settings)
Dead Code Stripping
Strip Debug Symbols During Copy
Strip Style

第五步 : 开启所有architecture支持

我们需要我们的framework可以用于所有的不同设备,所有不同的架构体系

"Build Active Architecture Only" => No (for all settings)
111.png

第六步: 生成架构(以framework的形式)

首先 : 创建文件目录布局

添加脚本
set -e

mkdir -p "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"

# Link the "Current" version to "A"
/bin/ln -sfh A "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/Current"
/bin/ln -sfh Versions/Current/Headers "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Headers"
/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}"

# The -a ensures that the headers maintain the source modification date so that we don't constantly
# cause propagating rebuilds of files that import these headers.
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
脚本展示

编译生成


Framework

生成的目录结构:

Serenity.framework/
    Headers/ -> Versions/Current/Headers
    Serenity -> Versions/Current/Serenity
    Versions/
        A/
        Headers/
            Serenity.h
            Widget.h
        Current -> A
接下来: 生成Framework的发布目标
  • 创建一个新的Aggregate 目标
创建一个新的Aggregate
  • 添加Static Library作为独立的目标
添加Static Library
  • 修改配置Architecture
修改配置
  • 构建其他平台

添加脚本

set -e
set +u
# Avoid recursively calling this script.
if [[ $SF_MASTER_SCRIPT_RUNNING ]]
then
    exit 0
fi
set -u
export SF_MASTER_SCRIPT_RUNNING=1

SF_TARGET_NAME=${PROJECT_NAME}
SF_EXECUTABLE_PATH="lib${SF_TARGET_NAME}.a"
SF_WRAPPER_NAME="${SF_TARGET_NAME}.framework"

# The following conditionals come from
# https://github.com/kstenerud/iOS-Universal-Framework

if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]
then
    SF_SDK_PLATFORM=${BASH_REMATCH[1]}
else
    echo "Could not find platform name from SDK_NAME: $SDK_NAME"
    exit 1
fi

if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]
then
    SF_SDK_VERSION=${BASH_REMATCH[1]}
else
    echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
    exit 1
fi

if [[ "$SF_SDK_PLATFORM" = "iphoneos" ]]
then
    SF_OTHER_PLATFORM=iphonesimulator
else
    SF_OTHER_PLATFORM=iphoneos
fi

if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$SF_SDK_PLATFORM$ ]]
then
    SF_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${SF_OTHER_PLATFORM}"
else
    echo "Could not find platform name from build products directory: $BUILT_PRODUCTS_DIR"
    exit 1
fi

# Build the other platform.
xcrun xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk ${SF_OTHER_PLATFORM}${SF_SDK_VERSION} BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" $ACTION

# Smash the two static libraries into one fat binary and store it in the .framework
xcrun lipo -create "${BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}" "${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}" -output "${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}"

# Copy the binary to the other architecture folder to have a complete framework in both.
cp -a "${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}" "${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}"

重要提示 :

  • 你可以在这里修改你的打包生成的Framework的名称
SF_TARGET_NAME=${PROJECT_NAME}
  • 你可以修改为
SF_TARGET_NAME=Serenity
  • 如果你有使用Cocoapods,你需要编译workspace 而不是project,如果你需要修改workspace相关内容,你可以修改一下脚本代码
xcrun xcodebuild ONLY_ACTIVE_ARCH=NO -workspace "${PROJECT_DIR}/${PROJECT_NAME}.xcworkspace" -scheme "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk ${SF_OTHER_PLATFORM}${SF_SDK_VERSION} BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" $ACTION

PS : 注意修改workspace setting.修改为legacy build system即可

构建与验证

编译Aggregate.

查找
验证文件

打开终端

lipo -info /Users/liliguang/...../Serenity.framework/Serenity(文件直接拖到终端)

终端打印信息

Architectures in the fat file: /Users/liliguang/...../Serenity.framework/Serenity are: i386 armv7 x86_64 arm64 

需要注意的是: 在这里面编译生成之后是没有包含armv7s, 关于iPhone5,5c的架构是armv7s,我测试过是在iPhone5,5c上运行也是没有问题的.最好也自己测试一下.



Resources and Bundles (资源包)

  • 第一步 : 创建Bundle

创建Bundle
  • 第二步 : 设置Bundle

默认的设置只配置了Mac OS X

设置Bundle

修改打包的Bundle Name

修改Bundle Name
  • 第三步 : 移除 HIDPI Mac OS X Build 设定

我们创建了一个OS X包,它包括并且选择合并HIDPI(视网膜和non-retina)媒体资源.tiff文件.你不希望这种行为,你需要禁用它,否则你将无法加载映像资产包。

简单来说,你现在加载了Bundle中的资源.同时项目中也可以通过assets中加载.避免冲突.你将所有的资源全部放在Bundle中使用.因为这是给别人使用的内容.

HIDPI
  • 给Bundle中添加资源

无论你什么会后添加资源,请选择Bundle


添加图片
  • 第四步 : 添加Bundle到你的Aggregate中

添加到Aggregate中
  • 第五步 : 读取Bundle资源

// Load the framework bundle.
+ (NSBundle *)frameworkBundle {
    static NSBundle* frameworkBundle = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        NSString* mainBundlePath = [[NSBundle mainBundle] resourcePath];
        NSString* frameworkBundlePath = [mainBundlePath stringByAppendingPathComponent:@"Bundle.bundle"];
        frameworkBundle = [NSBundle bundleWithPath:frameworkBundlePath];
    });
    return frameworkBundle;
}


代码自己简单研究下就可以了.

注意路径正确就好@"Bundle.bundle"




如果你的项目中需要资源. 你在发布的时候,需要将.framework与.bundle一起发给其他开发者.开发者直接拖动这两个文件到他们项目中就可以了...

(这里有个想法,能不能只拖动一个就可以了呢???)
思考其他Framework :
1.需不需要Bundle?也就是有没有相关的登录界面的UI素材?
2.有没有包含资源在一起的Framework创建方式?

我自己对比了一下,其他的SDK,其中也有很多关于Bundle在里面,应该也是和这种方式类似.

也有其他的创建Framework的方式,比如cocoa touch Framework,可以创建静态库和动态库.这种方式适合于纯方法创建.不适合带有UI的Framework. 择优选择吧.

总结

当开发一个框架时,满足你想减少构建时间同时确保你的内容大致匹配你的第三方开发者。我们实现这一平衡,只是构建static library,把static library当做像framework一样使用。

Github Demo

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

推荐阅读更多精彩内容