Object-C | 浅谈封装与静态库封装

定义

封装指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。而SDK封装通常是指动态库:.dylib/..framework.和静态库.framework.a

具体来说,封装就是把该隐藏的隐藏起来,把该暴露的暴露出来。这两个方面通过OC提供的访问控制符来实现。

访问控制符顺序

各控制符的作用:
默认:同一个包中的类可以访问。
1:@private(当前类访问权限):只能在当前类内部被访问。用于彻底隐藏成员变量。在类的实现部分定义的成员变量相当于默认用这种访问权限。 (私有的:只有该类可以访问,权限最小)
2:@package(与映像访问权限相同):可以在当前类以及当前类实现的同一个映像的任意地方访问。这个访问控制符用于部分隐藏成员变量。
3:@protected(子类访问权限):可以在当前类、当前类的子类的任意部分访问。用于暴露部分成员变量。在类的接口部分定义的成员变量默认使用这种访问权限。(受保护的:该类及其子类的成员可以访问,同一个包中的类也可以访问)
4:@public(公共访问权限):可以在任意部分访问,不管是否处于同一个映像中,不管是否具有父子继承关系。(该类或非该类均可访问,权限最大)

静态库 VS 动态库

静态库即是静态链接库,在编译时将代码拷贝进目标程序中,会导致目标程序的体积增加。被多次使用就会在内存中存在多份冗余拷贝静态库的代码就相当于是目标程序的一部分
动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到App启动时,动态库才会被真正加载。进行rebase指针调整bind符号绑定等工作,导致App的启动时间增长。由系统动态加载到内存,供App调用,系统只加载一次,多个程序共用,节省内存

苹果的动态库发展史

iOS 8之前,iOS平台不支持自定义动态库,开发者可以使用的动态库只能是苹果自家的 UIKit.frameworkFoundation.framework 等。这种限制的原因是出于安全考虑,因为iOS应用都是运行在沙盒中,不同的程序之间不能共享代码动态下载代码是苹果明令禁止的,既然没办法发挥动态库的优势,动态库也就没有存在的必要了。
iOS 8之前,也有一些第三方提供的.framework文件存在,但是它们本质上都是静态库,只不过通过一些方法进行了包装,相比较.a文件使用更方便一些。
iOS 8/Xcode 6推出后,iOS平台添加了动态库的支持,支持开发者有条件地创建和使用动态库,这种动态库叫做 Cocoa Touch Framework ,但是这种动态framework系统的framewor还是有很大区别的。系统的framework在编译时不需要拷贝进目标程序中,而 Cocoa Touch Framework 在打包和提交App时会被放到app bundle中,运行在沙盒里,不同的app就算使用了相同的framework也是会有多份的框架被分别签名、打包和加载,因此苹果又把这种framework称为在Embedded Framework
Cocoa Touch Framework的推出主要是为了解决两个问题:从iOS 8开始的扩展开发Swift在早期不支持编译为静态库

静态库.framework和.a的区别

.a是纯二进制文件 .framework中除了二进制文件还有资源文件
.a文件不能直接使用,需要引入.h文件配合 .framework文件包含了.h文件和其他文件,可以直接使用
.a文件是静态库,.framework 既可以是静态库也可以是动态库

关于如何制作.a文件.framework文件的教程网上特别多,这里我就不做具体描述。这里主要总结一下几个关键点。

架构

苹果的架构分为两大类:
模拟器架构 : i386 32位架构x86_64 64位架构
真机架构 : armv7 32位架构armv7s 特殊架构arm64 64位架构

合并架构

使用模拟器编译出来的包是模拟器架构,使用真机编译出来的包是真机架构。可以使用lipo -info查看当前包的架构类型。真机和模拟器架构合成的好处是调试会非常方便,缺点是体积会变大,一般而言,SDK都需要合成架构方便使用者使用。合并架构的命令:lipo -create simulator.a device.a -output name.a 合并.framework文件的架构命令也是使用lipo -create区别点是合成的是.framework文件内部的可执行文件

脚本打包

手动打包虽然能满足我们的需求,但是利用脚本打包会带来几点优势:

1:提高效率,原本繁琐的打包流程,只需要执行一下脚本就能完成
2:统一规范,繁琐的操作流程,依赖个人去完成,难免会出现差错,利用脚本可以确保准确性
3:易于使用,利用脚本打包,即使是新人也可以非常容易的上手,降低沟通成本

既然脚本打包有这么多优点,接下来就总结一下实现脚本打包的过程:

脚本打包思路

利用xcodebuild分别打包模拟器架构和真机架构
利用lipo -create合并模拟器和真机架构
如果是framework的合并,需要将合并了的二进制可执行文件复制到framework中
复制文件到指定目录下,并打开文件夹

脚本代码如下

# Sets the target folders and the finalframework product.

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

# 例如: FMK_NAME = "MyFramework"   你生成的就是MyFramework.Framework

FMK_NAME="MyTestFramework"

# Install dir will be the final output tothe framework.

# The following line create it in the rootfolder of the current project.

INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework

# Working dir will be deleted after theframework 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 binaryfiles (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}"

利用Aggregate提供快捷方法

在当前项目下新建Aggregate Target

新建Aggregate Target

添加Run Script

添加Run Script

在Run Script Phases输入脚本内容

在Run Script Phases输入脚本内容

编译Aggregate Target 完成脚本打包

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容