IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【Effective Objective-C】—— 系统框架 -> 正文阅读

[移动开发]【Effective Objective-C】—— 系统框架

熟悉系统框架

框架:将一系列代码封装为动态库,并在其中放入描述其接口的头文件,这样做出来的东西就叫做框架。
有时为iOS平台而构造的第三方框架所使用的是静态库,但所有iOS平台的系统框架仍然使用动态库。

要点:

  • 许多系统框架都可以直接使用。其中最重要的是FoundationCoreFoundation,这个框架提供了构建应用程序所需的许多核心功能。
  • 很多常见任务都能用框架来做,例如音频与视频处理、网络通信、数据管理等。
  • 请记住:用纯C写成的框架与用Objective-C写成的一样重要,若想成为优秀的 Objective-C开发者,应该掌握C语言的核心概念

多用块枚举,少用for循环

使用Objective-C 1.0的NSEnumerator来遍历

NSEnumerator是个抽象基类,其中只定义了两个方法,供其具体子类实现:

- (NSArray*)allObjects
- (id)nextObject

其中关键的方法是nextObject,它返回枚举里的下个对象。等到枚举中的全部对象都已返回之后,再调用就将返回nil。
Foundation框架中内建的collection类都实现了这种遍历方法。例如遍历数组:
请添加图片描述
虽然代码较for循环多了一点,但其真正的优势在:不论遍历哪种collection,都可以采用这套相似的语法。比如遍历字典和set:
请添加图片描述

快速遍历

自Objective-C 2.0引入了快速遍历这一功能。它为for循环开设了in关键字,比如要遍历数组:
请添加图片描述
如果某个类的对象支持快速遍历,则可以宣称自己遵从名为NSFastEnumeration的协议,从而令开发者可以采用此语法来迭代该对象。此协议只定义了一个方法:
请添加图片描述

该方法允许类实例返回多个对象,这就使得循环遍历操作更为高效。
由于NSEnumerator对象也实现了NSFastEnumeration协议,所以也可以用来执行反向遍历。例如:反向遍历数组:
请添加图片描述

基于块的遍历方式

在当前的Objective-C语言中,最新引入的一种做法就是基于块来遍历。NSArray中定义了下面这个方法,它可以实现最基本的遍历功能:
请添加图片描述
这个块有三个参数:分别是当前迭代所针对的对象,所针对的下标,以及指向布尔值的指针。通过最好一个参数提供的机制,开发者可以终止遍历操作。
例如:遍历数组:
在这里插入图片描述
此方法不仅可以用来遍历数组,还可以用来遍历NSSet或者NSDictionary:
请添加图片描述
请添加图片描述
块的方法签名可以修改,以免进行类型转换操作。比方说,要用“快速遍历法”来遍历字典。若已知字典中的对象必为字符串,则可以这样编码:
请添加图片描述
但是改为基于块的方式来遍历,那么就可以在块方法签名中直接转换:
请添加图片描述

要点:

  • 遍历collection有四种方式。最基本的办法是for循环,其次是NSEnumerator遍历法及快速遍历法,最新、最先进的方式则是“块枚举法”。
  • “块枚举法”本身就能通过GCD来并发执行遍历操作,无须另行编写代码。而采用其他遍历方式则无法轻易实现这一点。
  • 若提前知道待遍历的collection含有何种对象,则应修改块签名,指出对象的具体类型。

对自定义其内存管理语义的collection使用无缝桥接

要点:

  • 通过无缝桥接技术,可以在Foundation 框架中的 Objective-C对象与CoreFoundation框架中的C语言数据结构之间来回转换。
  • CoreFoundation 层面创建 collection 时,可以指定许多回调函数,这些函数表示此 collection 应如何处理其元素。然后,可运用无缝桥接技术,将其转换成具备特殊内存管理语义的 Objective-C collection

构建缓冲时选用NSCache而非NSDictionary

开发时,经常会遇到一个问题,那就是从英特网下载的图片应如何缓冲。大部分程序员都是将其保存到字典里,这样的话稍后使用时就无需再次下载了。但是NSCache这个类更好,它是Foundation框架专为处理这种任务而设计的。

当系统资源将要耗尽时,它可以自动删减缓冲,这是NSDictionary所不具备的,此外,NSCache还会先行删减“最久未使用的”对象。NSCache不会“拷贝”键,而是会“保留”它。且NSCache是线程安全的,在开发者自己不编写加锁代码的前提下,多个线程可以同时访问NSCache

在编写缓冲代码时,可以借助NSPurgeableData,二者搭配使用效果更佳。此类是NSMutableData的子类,而且实现了NSDiscardableContent协议。如果某个对象所占的内存能够根据需要随时丢弃,那么就可以实现该协议所定义的接口。这就是说,当系统资源紧张时,可以把保存NSPurgeableData对象的那块内存释放掉。NSDiscardableContent协议里定义了名为isContentDiscarded的方法,可用来查询相关内存是否已释放。

在需要访问某个NSPurgeableData对象时,可以调用beginContentAccess方法,用完之后可以调用endContentAccess方法。这些调用可以嵌套,所以就像引用计数机制一样。

如果将NSPurgeableData对象加入NSCache,那么当该对象为系统所丢弃时,也会自动从缓冲中移除。通过NSCacheevictsObjectsWithDiscardedContent属性,可以开启或者关闭此功能。

创建好NSPurgeableData对象之后,其“purge引用计数”会多一,所以无须在调用beginContentAccess了,然而其后必须调用endContentAccess,将多出来的“1”取消掉。

要点:

  • 实现缓存时应选用NSCache而非NSDictionary对象。因为NSCache可以提供优雅的自动删减功能,而且是“线程安全的”,此外,它与字典不同,并不会拷贝键。
  • 可以给NSCache对象设置上限,用以限制缓存中的对象总个数及“总成本”,而这些尺度则定义了缓存删减其中对象的时机。但是绝对不要把这些尺度当成可靠的“硬限制”(hard limit),它们仅对NSCache起指导作用。
  • NSPurgeableDataNSCache搭配使用,可实现自动清除数据的功能,也就是说,当NSPurgeableData 对象所占内存为系统所丢弃时,该对象自身也会从缓存中移除。
  • 如果缓存使用得当,那么应用程序的响应速度就能提高。只有那种“重新计算起来很费事的”数据,才值得放入缓存,比如那些需要从网络获取或从磁盘读取的数据。

精简initialize与load的实现代码

有时候,有一些类必须执行初始化操作,然后才能正常使用。在Objective-C中,绝大多数类都继承至NSObject这个根类,而该类有两个方法,可用来实现这种初始化操作。
首先说一下load方法,对于加入运行期系统的每个类及分类来说,必定会调用此方法,且仅调用一次。如果分类和其所属的类都定义了load方法,则先调用类里的,再调用分类里的。

load方法中使用其他类是是不安全的,因为无法确认其他类是否已经加载好了。

load方法不像普通的方法那样,它并不遵从继承。如果某个类本身没实现load方法,那么不管其各级超类是否实现了此方法,系统都不会调用。

load尽量精简一些,能不写的代码就不要写,避免引起程序无响应。

除了load方法,就是initialize方法。对于每个类来说,该方法会在程序首次用该类之前调用,且只调用一次。它是由运行期系统来调用的,绝不是通过代码来直接调用。它与load不同,它是“惰性调用”,只有在用到相关类的时候才会调用;在运行期系统执行initialize方法时,是处于正常状态的;initialize方法与其他消息一样,如果某个类没实现它,而其超类实现了,那么就会运行其超类的实现代码,所以initialize是遵循继承规则的。

load和initialize都是尽量使这两个方法的实现代码精简,不要执行那种耗时或加锁的任务。

要点:

  • 在加载阶段,如果类实现了load方法,那么系统就会调用它。分类里也可以定义此方法,类的load 方法要比分类中的先调用。与其他方法不同,load方法不参与覆写机制。
  • 首次使用某个类之前,系统会向其发送initialize消息。由于此方法遵从普通的覆写规则,所以通常应该在里面判断当前要初始化的是哪个类。
  • loadinitialize 方法都应该实现得精简一些,这有助于保持应用程序的响应能力,也能减少引人“依赖环”(interdependencycycle)的几率。
  • 无法在编译期设定的全局常量,可以放在initialize 方法里初始化。

别忘了NSTimer会保留其目标对象

计时器要和“运行循环(run loop)”相关联,运行循环到时候会触发任务。只有把NSTimer放到运行循环里,才能正常触发任务。

要点 :

  • NSTimer对象会保留其目标,直到计时器本身失效为止,调用invalidate方法可令计时器失效,另外,一次性的计时器在触发完任务之后也会失效。
  • 反复执行任务的计时器(repeatingtimer),很容易引入保留环,如果这种计时器的目标对象又保留了计时器本身,那肯定会导致保留环。这种环状保留关系,可能是直接发生的,也可能是通过对象图里的其他对象间接发生的。
  • 可以扩充 NSTimer 的功能,用“块”来打破保留环。不过,除非NSTimer将来在公共接口里提供此功能,否则必须创建分类,将相关实现代码加入其中。
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:56:51  更:2022-03-13 21:57:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 17:18:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码