【iOS】系统框架

文章目录

  • 前言
  • 四十七、熟悉系统框架
  • 四十八、多用块枚举,少用for循环
  • 四十九、对自定义其内存管理语义的collection使用无缝桥接
  • 五十、构建缓存时选用NSCache而非NSDictionary
  • 五十一、精简initialize与load的实现代码
  • 五十二、别忘了NSTimer会保留其目标对象


前言

本次博客撰写小蓝书的最后一章系统框架

四十七、熟悉系统框架

OC的Foundation框架,像NSObject NSArray, NSDictionary等类都在其中。Foundation框架里的类都是用NS前缀,因为OC之前作为NeXTSTEP操作系统确定的。

将一系列代码封装为动态库,并在其中放入描述其接口的头文件,这样做出来的东西就叫框架。

CoreFoundation框架

Foundation框架提供了collection等基础核心功能,而且还提供了字符串处理等复杂功能。还存在一个CoreFoundation框架,在之前了解过他是不属于OC框架之内的,但是OC应用程序的编写离不开这个框架,Foundation框架的许多功在CoreFoundation框架都可以找到对应的C语言API

他其中的很多类都和Foundation框架相似,并且我们还可以通过“无缝桥接”功能实现CoreFoundation框架中的C语言数据结构平滑转换为Foundation框架中的OC对象,也可以反向转换。无缝桥接技术是用某些相当复杂的代码实现出来的,这些代码可以使运行期系统把CoreFoundation框架中的对象视为普通的OC对象。

NSString所对应的就是CFString对象。

其他框架:
在这里插入图片描述
OC编程的重要特点就是:经常需要使用底层的C语言级 API。用c语言实现 API的好处是,可以统过 Objeotive-C 的运行期系统,从而提升执行速度

要点

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

四十八、多用块枚举,少用for循环

语言中引人“块” 这一特性后,又多出来儿种新的通历方 式,而这几种方式容易为开发者所忽视。采用这几种新方式遍历collection 时,可以传人块, 而collection 中的每个元素都可能会放在块里运行一遍,这种做法通常会大幅度简化编码过程以下进行各种遍历方法详细说明:

for循环
在这里插入图片描述
根据定义,因为字典与set对象是无需的,所以无法通过下标访问,所以需要先获取字典里的所有键值或是set中的所有对象,这两种情况下都可以放到数组中实现,就如上述代码所显示

NSEnumerator遍历
NSEnumerator是个抽象基类,其中只定义了两个方法,供其具体子类来实现:
在这里插入图片描述
关键的是其中的nextObject对象,它返回枚举里的下个对象,当返回不为nil的时候就会一直调用下一个对象,常用while语句

对于set与字典写法其实也与标准的for循环相似,只是代码多了一些,其优势在于无论遍历哪一种collection,都可以采用这套相似的语法
在这里插入图片描述

快速遍历
快速遍历是OC2.0引入的语法功能,引入了in关键字,语法更加简洁了collection的遍历过程。尤其是字典类
在这里插入图片描述

基于块的遍历方式
在这里插入图片描述
参数1是每次枚举的对象, idx是下标, stop则是代表是否停止遍历

使用这种方法遍历时既能获取对象,也能知道其下标

    [t enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {NSLog(@"%@ %lu", obj, (unsigned long)idx);      }];

对于字典,还可获得其key与object
在这里插入图片描述

此方式大大胜; 过其他 方式的地方在于:遍历时可以直接从块里获取更多信息。在遍历数 组时,可以知道当前所针对的下标。遍历有序set (
NSOrderedset )时也一样。而在遍历字典 时, 无须额外编码,即可同时获取键与值,因而省去了根据给定键来获取对应值这一步。用
这种方式遍历字典,可以同时得知键与值,这很可能比其他方式快很多,因为在字典内部的 数据结构中,键与值本来就是存储在一起的。

在这里插入图片描述
同时还可通过选项掩码进行反向遍历

要点

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

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

Objective-C的系统库包含相当多的collection 类,其中有各种数组、各种字典、各种 setoFoundation框架定义了这些collection及其他各种collection所对应的Objective-C类 。与 之相似,CoreFoundation 框架也定义了一套C语言API,用于操作表示这些collection 及其他 各种collection 的数据结构。

例如,NSAray 是Foundation 框架中表示数组的Objective-C类, 而CFArray 则是CoreFoundation 框架中的等价物。这两种创建数组的方式也许有区别,然而 有 项 强 大 的 功 能 可 在 这 两 个 类 型 之 间 平 滑 转 换, 它 就 是 “ 无 缝 桥 接” ( t o l l - f r e e b r i d g i n g ) 。

转换操作中的__bridge告诉ARC如何处理转换所涉及的OC对象。__bridge本身的意思是:ARC仍然具备这个OC对象的所有权。而__bridge_retained则与之相反,意味着ARC将交出对象的所有权。与之相似,反向转换可通过__bridge_transfer来实现,也就是将对象的所有权交给ARC。这三种转换方式称为“桥式转换”

- (void)seamlessBridging {NSArray *testArray = @[@"111", @"222", @"333",];CFArrayRef aCFArray = (__bridge  CFArrayRef)testArray;NSLog(@"cfArratSize =  %li", CFArrayGetCount(aCFArray));
}

要点

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

五十、构建缓存时选用NSCache而非NSDictionary

开 发 M a c O s × 或 i 0 s 应 用 程 序 时 , 经 常 会 遇 到 一个 问 题 , 那 就 是 从 因 特 网 下 载 的 图 片 应如何来缓存。首先能想到的好办法就是把内存中的图片保存到字典里,这样的话,稍后使 用 时 就 无 须 再 次 下 载 了。 有 些 程 序 员 会 不 假 思 索 , 直 接 使 用 N S D i c t i o n a r y 来 做 (准 确 来 说 , 是使用其可变版本),因为这个类很常用。其实,NSCache 类更好,它是Foundation 框架专 为处理这种任务而设计的。

NSCache 胜过NSDictionary 之处在于,当系统资源將要耗尽时,它可以自动删减缓存
另外,NSCache 是线程安全的。 而NSDictionary 则绝对不具备此优势

要点

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

五十一、精简initialize与load的实现代码

在OC里一个类必须初始化才能使用,大多数类继承与NSObject这个根类,提供了loadinitalize方法

load
加入运行期系统中的每个类和分类来说,会调用此方且仅调用一次,当类和分类的程序载入系统的时候就会执行这个方法,调用顺序是类大于分类

总结一句话就是不要用load

initalize
该方法是在程序首次使用该类之前调用且仅有一次,是由运行期系统调用的,不通过代码调用。和load存在区别

  • 惰性调用当程序用到了相关类的时候才会调用,类似于懒加载模式。而load是所有类不管用不用先load方法之后再说
  • 其次运行期在执行该方法的时候是系统正常状态,也就是安全状态,不影响调用类的其他方法,此为线程安全。
  • 当某个类没实现initialize方法,超类实现后会调用超类的方法,和大多数消息是一样的。

initalize方法尽量精简

  • 首先,大家都不想看到自己的应用程序“挂起”,若写的太过繁琐,导致其运行很慢那就适得其反了。
  • 开发者无法控制类的初始化时机。
  • 最后,如果某个类的实现代码很复杂,那么其中可能会直接或间接用到其他类。若那些类尚未初始化,则系统会迫使其初始化。然而,本类的初始化方法此时尚未运行完毕。其他类在运行其initialize方法时,有可能会依赖本类中的某些数据,而这些数据此时也许还未初始化好,就会造成依赖环

initalize方法只应该用来设置内部数据,不能在内部调用其他的方法。

initalize还可以初始化某个无法在编译器初始化的全局变量
在这里插入图片描述
但别忘了单例类也可以实现该目的

要点

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

五十二、别忘了NSTimer会保留其目标对象

Foundation框架中有个类叫NSTimer,开发者可以指定绝对的日期与时间,以便到时执行任务,计时器要和“运行循环(run loop)”相关联,运行循环到时候会触发任务。创建NSTimer时,可以将其“预先安排”在当前的运行循环中,也可以先创建好,然后由开发者自己来调度。无论采用哪种方式,只有把计时器放在运行环里,它才能正常触发任务

创建计时器

 _pollTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(pDoPoll) userInfo:nil repeats:YES];

保留环

创建计时器的时候,由于目标对象是self,所以要保留此实例。然而,因为计时器是用实例变量存放的,所以实例也保留了计时器,于是,就产生了保留环。所以说,调用stopPolling,或者令系统将此实例回收,只有这样才能打破保留环。

因为是类和这个类中的实例出现了保留环,不管你外界怎么对这个类释放,这个计时器始终都会保留这个类,而这个类也会保留这个计时器,互相引用保留导致他们的计数永远都不会降为0

在这里插入图片描述
如果从外界直接先调用stop方法,代码没办法自己检测。

使用块的特点打破保留环

使用块和weak关键字合理的打破保留环,块可以传递代码,这一功能可以利用
在这里插入图片描述
在这里插入图片描述
这个办法为何能解快“ 保留环〞问题呢?大家马上就会明白。这段代码将计时器所应执 行的任务封装成“ 块”,在调用计时器西数时,把它作为userlnfo 参数传进去。该参数可用来 存 放 “ 不 透 明 值 ” ( o p a q u e v a l u e )。 , 只 要 计 时 器 还 有 效 , 就 会 一直 保 留 着 它 。 传 人 参 数 时 要 通 过copy方法将block拷贝到“堆” 上(之前在blk提过,copy方法把块变成了有引用计数的对象。),否则等到稍后要执行它的时候,该块 可能己经无效了。计时器现在的target 是NSTimer 类对象,这是个单例,因此计时器是否会 保 留 它, 其 实 都 无 所 谓 。 此 处 依 然 有 保 留 环 , 然 而 因 为 类 对 象 ( c l a s s o b j e c t ) 无 须 回 收 , 所 以 不用担心。

此处依然有保留环,使用weak关键字打破它
在这里插入图片描述
这 段 代 码 采 用 了一 种 很 有 效 的 写 法 , 它 先 定 义 了一 个 弱 引 用 , 令 其 指 向 s e l f , 然 后 使 块 捕获这个引用,而不直接去捕获普通的sel f 变量。也就是说,sel f 不会为计时器所保留。当 块开始执行时,立刻生成strong 引用,以保证实例在执行期间特续存活。

采用这种写法之后,如果外界指向EOCClass实例的最后 一个引用将其释放,则该实例 就 可 为 系 统 所 回 收 了。

要点

  • NSTimer对象会保留其目标,直到计时器本身失效为止,调用invalidate方法可令计时器失效,另外,一次性的计时器在触发完成任务之后也会失效。
  • 反复执行任务的计时器,很容易引人保留环,如果这种计时器的目标对象又保留了计时器本身,那肯定会导致保留环。这种环状保留关系,可能是直接发生的,也可能是通过对象图里的其他对象间接发生的。
  • 可以扩充NSTimer的功能,用“块” 来打破保留环。不过,除非NSTimer将来在公共接口里提供此功能,否则必须创建分类,将相关实现代码加入其中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/690744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

E. Final Countdown

思路:对于每一位统计贡献,不难发现,假设数为12345,个位的贡献就是12345, 十位的贡献是1234(仅当个位跳转时产生贡献),百位贡献是123,后面同理。 12345 1234 123 12 1 …

Stable Diffusion 模型下载:Dark Sushi Mix 大颗寿司Mix

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 Dark Sushi Mix 大颗寿司Mix 是一个动漫大模型,绘制的图片色彩丰富…

网络运行安全

网络运行安全 第一节 一般规定 第二十一条 国家实行网络安全等级保护制度。网络运营者应当按照网络安全等级保护制度的要求,履行下列安全保护义务,保障网络免受干扰、破坏或者未收授权的访问,防止网络数据泄露或者被窃取、篡改: 制定内部安全管理制度和操作规程,确定网络…

【MySQL初阶】索引

1. 索引基本概念 1.1 索引介绍 索引(index):是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或者多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。(具体细节在MySQL进阶章节详…

SNAT与DNAT公私网地址转换

前言 SNAT和DNAT是两种重要的网络地址转换技术,它们允许内部网络中的多个主机共享单个公共IP地址,或者将公共IP地址映射到内部网络中的特定主机。这些技术在构建企业级网络和互联网应用程序时非常重要,因为它们可以帮助保护内部网络安全&…

安全名词解析-攻防演练

为方便您的阅读,可点击下方蓝色字体,进行跳转↓↓↓ 01 攻防演练 01 攻防演练 《网络安全法》中明确提出,“定期组织关键信息基础设施的运营者进行网络安全应急演练,提高应对网络安全事件的水平和协同配合能力。”攻防演练目前已经…

0、电源管理入门之开篇即巅峰

目录 1. 电源状态介绍 2. Linux 电源管理的组成 3. ARM SoC中PCSA与SCP 4. SoC设计中的电源管理 “人是铁饭是钢,一顿不吃饿得慌”,对于嵌入式设备而言,没有电一切都白瞎,特别是带电池的终端嵌入式设备,对电能的管理尤其重要,也是我们调试设备的一个重点。可以说…

linux高级作业

作业需求 1、openEuler 二进制方式安装MySQL 8.0.x。 二、备份数据库 3.备份数据库school到/backup目录 4.备份MySQL数据库为带删除表的格式,能够让该备份覆盖已有数据库而不需要手动删除原有数据库 5.直接将MySQL数据库压缩备份 第一题 1、openEuler 二进制方式…

爬虫知识--01

爬虫介绍 # 爬虫的概念: 通过编程技术(python:request,selenium),获取互联网中的数据(app,小程序,网站),数据清洗(xpaht,lxml)后存到库中(mysql,redis,文件,excel&#x…

如何选择合适的三防平板?

一、随着移动互联网的快速发展,平板电脑作为一种轻便、易携带的移动设备已经成为了人们生活中必不可少的一部分。在一些特殊的工作环境下,例如工地、野外等场景,常规的平板电脑可能无法满足使用要求,因此人们需要选择一款具有防水…

【漏洞复现-通达OA】通达OA get_file.php 任意文件下载漏洞

一、漏洞简介 通达OA get_file.php文件存在任意文件下载漏洞,攻击者通过漏洞可以读取服务器敏感文件。 二、影响版本 ● 通达OA2011 三、资产测绘 ● hunterapp.name"通达 OA" ● 特征 四、漏洞复现 GET /module/AIP/get_file.php?MODULE/&A…

docker 服务的启动命令

Docker 服务的启动命令主要涉及 Docker Daemon 的启动和管理。Docker Daemon 是在后台运行的服务进程,负责管理 Docker 容器的创建、运行、停止等操作。根据你使用的操作系统,启动 Docker 服务的命令可能有所不同。 对于 Linux 系统 使用 systemctl (适…

如何在Excel中冻结行或列标题?这里提供两种方法

随着数据的增长,许多Excel工作表可能会变得很大,因此冻结行和列标题或冻结窗格非常有用,以便在滚动工作表时将标题锁定到位。在Excel中,可以冻结行标题和列标题,也可以只冻结一个。这不会影响将要打印的单元格。列标题…

Excel常用快捷键(持续更新)

引言 excel是我们办公中经常使用的工具,古语言“工欲善其事必先利其器”。excel是一个好的工具,但是工具里面有很多常用的快捷键,若我们熟记这些快捷键,便可以提高我们的工作效率。本文为持续更新,望有助于搬砖。 1、C…

SICTF Round#3 wp web

web hacker sql无列名注入; 提示查询username参数,flag在flag表中; 传参测试发现,union select 可用,空格被过滤可以使用/**/代替 ,or也被过滤了且无法大小写、双写等绕过,导致无法查询flag表…

微信小程序swiper 视频中间大,两边小,轮播滑到中间视频自动播放组件教程

静态效果&#xff1a; 进入下面小程序可以体验效果&#xff0c;点击底部 看剧 栏目 一、创建小程序组件 二、代码 1、WXML <view class"swiper-wrapper" style"background-image:url(/asset/image/hot-banner.jpg);background-size: 100% 100%;">…

正整数A+B(PTA团体天题练习题)细节题刨析

哎呀&#xff0c;又是看似简单的AB模型&#xff0c;这题确实也是AB&#xff0c;不过这个题让我debug1个多小时才找出来问题所在&#xff0c;服了&#xff0c;真是所谓细节决定成败&#xff0c;这题也挺值得记录下来的&#xff0c;话不多嗦&#xff0c;看题 题的目标很简单&…

RK3568平台开发系列讲解(Linux系统篇)内核中断机制

🚀返回专栏总目录 文章目录 一、注册中断处理程序二、下半部的概念2.1、Tasklet作为下半部2.2、工作队列作为下半部2.3、Softirq作为下半部沉淀、分享、成长,让自己和他人都能有所收获!😄 📢中断是设备中止内核的一种方法,告诉内核发生了有趣或重要的事情。这些在Linu…

docker环境常用容器安装

目录 1.安装partainer 2.安装myql 3.安装redis 4.安装Minio 5.安装zibkin 6.安装nacos 7.安装RabbitMq 8.安装RocketMq 8.1启动service 8.2修改对应配置 8.3启动broker 8.4启动控制台 9.安装sentinel 10.安装elasticsearch 11.安装Kibana 12.安装logstash/file…

《UE5_C++多人TPS完整教程》学习笔记14 ——《P15 创建我们自己的子系统(Creating Our Own Subsystem)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P15 创建我们自己的子系统&#xff08;Creating Our Own Subsystem&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&…