当前位置: 首页 > news >正文

《Effective Objective-C》阅读笔记(中)

目录

接口与API设计

用前缀避免命名空间冲突

提供“全能初始化方法”

实现description方法

尽量使用不可变对象

使用清晰而协调的命名方式

方法命名

​编辑类与协议命名

为私有方法名加前缀

理解OC错误模型

理解NSCopying协议

协议与分类

通过委托与数据源协议进行对象间通信

将类的实现代码分散到便于管理的数个分类之中

总是为第三方类的分类名称加前缀

​使用"class-continuation分类"隐藏实现细节

通过协议提供匿名对象


接口与API设计

用前缀避免命名空间冲突

为了避免“重名符号错误”,应当为所有名称都加上适当前缀,可以与公司、程序或二者皆有关。

但使用Cocoa创建程序时,要注意Apple保留使用所有“两字母前缀”的权利,所以开发者使用的前缀应该是三个字母的

不仅是类,还有C函数的名字也应加上前缀

如果是开发第三方库,那么对于所有包含的第三方库代码都加上自己的前缀。

提供“全能初始化方法”

可以为对象提供必要信息以便其能完成工作的初始化方法叫做“全能初始化方法”。

在上图方法中,initWithTimeIntervalSinceReferenceDate:便是全能初始化方法。

当一个类有多个初始化方法时,仍要选定一个作为全能初始化方法,其他初始化方法都调用它。

只有在全能初始化方法中,才会存储内部数据,这样的话,当底层数据存储机制改变时,只需修改此方法的代码就好。

如果子类的全能初始化方法与超类方法的名称不同,那么总应覆写超类的全能初始化方法。

实现description方法

在自定义类中,description的默认实现是打印类名和地址,输出信息如下:

这时我们应尽量将输出信息改为一个有意义的字符串,用来描述这个实例。有个简单的方法,就是借助NSDictionary的description方法。此方法输出的信息的格式如下:

字符串可以采用如下格式:

若想在调试时打印更详尽的描述信息,应实现debugDescripption方法。

尽量使用不可变对象

在编程实践中,应该尽量把对外公布出来的属性设为只读,而只在确有必要时才将属性对外公布。

有时可能想修改封装在对象内部的数据,但是不想让这些数据为外人所改动,这种情况下通常做法是将readonly重新声明为readwrite,这一操作应该在"class-continuation分类"中完成。

在定义类的公共API时,还应注意:对象里表示各种collection的那些属性应该设成可变的,还是不可变的。

比如:我们用某个类来表示个人信息,该类中还存放了一些引用指向此人的朋友,开发者可以添加或删除朋友,那这个属性就要用可变的set来实现。这种情况下,通常应该提供一个readonly属性供外界使用,返回一个不可变的set,这个set是内部可变set的一份拷贝。比如下面这份代码:

使用清晰而协调的命名方式

OC当中方法与变量名采用“驼峰式大小写命名法”,而类名首字母大写,并且有两三个前缀字母。

方法命名

命名方法时,应当使方法像个日常用语中的句子,准确传达方法所执行的任务,然而方法名不能长得太过分,应尽量言简意赅。

类与协议命名

类与协议的名称应加上前缀,并且应该像给方法起名一样组织好词句,使从左至右比较通顺。

为私有方法名加前缀

在编写私有方法时,最好使用前缀将私有方法标注出来,前缀最好包含下划线与字母p。

要注意不应该直接使用下划线作为私有方法的前缀,因为苹果公司喜欢单用一个下划线作为私有方法的前缀,使用一个下划线有可能会无意中覆写超类中的其他方法。

理解OC错误模型

自动引用计数不是“异常安全”的,并且即使不用ARC,也很难写出在抛出异常时不会导致内存泄漏的代码。所以OC语言当中,异常只用于极其严重的错误,抛出异常之后,应用程序应该退出,也就无需考虑恢复问题了

在出现不那么严重的错误时,OC语言所用的编程范式为:令方法返回nil/0,或是使用NSError,以表明其中有错误发生。

NSError的用法更加灵活,NSError对象里封装了三条信息:

Error domain:错误发生的范围,也就是产生错误的根源。

Error code:独有的错误代码,用以指明在某个范围内具体发生了何种错误。

User info:有关此错误的额外信息。

NSError有两种常见用法,一种是通过委托协议来传递错误,另一种是经由方法的“输出参数”返回给调用者。

理解NSCopying协议

OC中如果想令自己的类支持拷贝操作,那就要实现NSCopying协议,该协议只有一个方法:

这里zone参数不用考虑,使用默认参数即可。比如游客表示个人信息的类,可以声明遵从NSCopying协议:

有时需要获取可变的拷贝,则应遵守NSMutableCopying协议,该协议也只定义了一个方法:

当对象需要深拷贝时,可考虑吧新增一个专门执行深拷贝的方法

协议与分类

通过委托与数据源协议进行对象间通信

OC开发中经常使用一种“委托模式”,主旨是:定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以成为其“委托对象”,而这另一个对象,则可以给其委托对象回传一些信息,也可以在发生相关事件时通知委托对象。一般通过协议来实现委托模式。

用一张图来演示委托模式的概念:

这里EOCDataModel1就是作为EOCNetwirkFetcher的委托对象。

但是要注意,类中存放委托对象的属性需定义成weak,而非strong:

@interface EOCNetworkFetcher : NSObject
@property (nonatomic, weak) id <EOCNetworkFetcherDelegate> delegate;
@end

因为通常delegate要持有本对象,若本对象也持有delegate,那么就会引入保留环。

实现委托对象可以在接口中声明,也可以在“class-continuation分类”中声明。如果要向外界公布此类实现了某协议,那么就在接口中声明,如果是委托协议,通常只在类内部使用,一般在"class-continuation分类"里声明。

还有另一种,令某类经由协议中接口获取所需的数据,被称为“数据源模式”。

若有必要,可实现含有位段的结构体,将委托对象是否能相应相关协议方法这一信息缓存至其中。

将类的实现代码分散到便于管理的数个分类之中

当类中存在大量方法的代码时,可以通过OC的分类机制,把类代码按逻辑划入几个分区中。

比如下面这个管理个人信息的类:

可以把不同的方法放入不同分类中:

这些分类可以全部放在一个实现文件中,但当存在许多分类时,最好每个分类提取到各自的文件中去。以EOCPerson为例,可以拆分成下列这几个文件:

私有方法应归入名叫Private的分类中,以隐藏实现细节。

总是为第三方类的分类名称加前缀

我们经常通过分类为无源码的既有类添加方法,这时就容易出现命名冲突的问题。我们应该为分类和方法添加了前缀。

比如为NSString添加分类处理HTTP URL有关的字符串。

我们为其加上前缀:

使用"class-continuation分类"隐藏实现细节

class-continuation分类"和普通的分类不同,他必须定义在其所接续的那个类的实现文件里,这是唯一能声明实例变量的分类。

这种分类在实现文件中格式如下:

通过这种分类可以获得隐藏程度更好的私有方法和私有变量。

除了获得隐藏变量和方法之外,使用这种分类还可以将只读的属性扩展为可读写的,以便在类的内部设置其值。

还有一种用法是,当对象所遵从的协议只应视为私有,则可在该分类中声明

通过协议提供匿名对象

有时,我们可以把返回的对象设计为遵从某协议的id类型,这样的话,想要隐藏的类名就不会出现在API之中了。若接口背后有多个不同的实现类,又不想指明具体使用哪个,可以考虑用这个方法,此概念被称为“匿名对象”。

有时对象类型不重要,重要的是有没有实现某些方法,在此情况下,也可以使用这些“匿名类型”来表达这一概念。

比如对受委托者的定义:

相关文章:

《Effective Objective-C》阅读笔记(中)

目录 接口与API设计 用前缀避免命名空间冲突 提供“全能初始化方法” 实现description方法 尽量使用不可变对象 使用清晰而协调的命名方式 方法命名 ​编辑类与协议命名 为私有方法名加前缀 理解OC错误模型 理解NSCopying协议 协议与分类 通过委托与数据源协议进行…...

LSM-Tree (日志结构合并树)

LSM-Tree&#xff08;日志结构合并树&#xff09;是一种高效处理写操作的存储结构&#xff0c;广泛应用于NoSQL数据库如LevelDB和RocksDB。其核心思想是将随机写入转换为顺序写入&#xff0c;提升吞吐量。以下是其原理及Java实现示例&#xff1a; ### **LSM-Tree 原理** 1. **…...

【深入理解JWT】从认证授权到网关安全

最近的项目学习中&#xff0c;在进行登陆模块的用户信息验证这一部分又用到了JWT的一些概念和相关知识&#xff0c;特在此写了这篇文章、方便各位笔者理解JWT相关概念 目录 先来理解JWT是什么&#xff1f; 区分有状态认证和无状态认证 有状态认证 VS 无状态认证 JWT令牌的…...

利用 Open3D 保存并载入相机视角的简单示例

1. 前言 在使用 Open3D 进行三维可视化和点云处理时&#xff0c;有时需要将当前的视角&#xff08;Camera Viewpoint&#xff09;保存下来&#xff0c;以便下次再次打开时能够还原到同样的视角。本文将演示如何在最新的 Open3D GUI 界面&#xff08;o3d.visualization.gui / o…...

智绘教:Windows平台上的高效悬浮窗画笔工具深度解析

在Windows平台上,一款高效、实用的悬浮窗画笔工具对于提升工作效率和演示效果至关重要。今天,我要为大家介绍一款备受好评的悬浮窗画笔程序——智绘教。这款软件以其丰富的功能和便捷的操作,成为了众多用户心中的首选。接下来,让我们一起深入了解智绘教的各项特性。 一、体…...

从“Switch-case“到“智能模式“:C#模式匹配的终极进化指南

当代码开始"思考" 你是否厌倦了层层嵌套的if-else地狱&#xff1f;是否想过让代码像侦探推理一样优雅地解构数据&#xff1f;C#的模式匹配正是这样一把瑞士军刀&#xff0c;从C# 7.0到C# 12&#xff0c;它已悄然进化成改变编程范式的利器。 一、模式匹配的三重境界…...

【Linux】进程优先级 | 进程调度(三)

目录 前言&#xff1a; 一、进程优先级&#xff1a; 1.通过nice值修改优先级&#xff1a; 二、进程切换&#xff1a; 三、上下文数据 四、Linux真实调度算法&#xff1a; 五、bitmap位图&#xff1a; 六、命令总结&#xff1a; 总结&#xff1a; 前言&#xff1a; 我…...

wordpress按不同页调用不同的标题3种形式

在WordPress中&#xff0c;可以通过多种方式根据不同的页面调用不同的标题。这通常用于实现SEO优化、自定义页面标题或根据页面类型显示不同的标题内容。 使用wp_title函数 wp_title函数用于在HTML的title标签中输出页面标题。你可以通过修改主题的header.php文件来实现自定义…...

音频进阶学习十六——LTI系统的差分方程与频域分析一(频率响应)

文章目录 前言一、差分方程的有理式1.差分方程的有理分式2.因果系统和ROC3.稳定性与ROC 二、频率响应1.定义2.幅频响应3.相频响应4.群延迟 总结 前言 本篇文章会先复习Z变换的有理分式&#xff0c;这是之前文章中提过的内容&#xff0c;这里会将差分方程和有理分式进行结合来看…...

css实现左右切换平滑效果

2025.02.25今天我学习了如何用css实现平滑效果 一、html相关代码 &#xff08;1&#xff09;设置往左、往右的动画属性&#xff0c;样式可以放在同一级。 &#xff08;2&#xff09;必须设置唯一key进行刷新数据&#xff0c;使用v-show来展示每次渲染的组件数量。 <tran…...

详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)

目录 步骤一&#xff1a;首先确认自己是否已经安装JDK步骤二&#xff1a;下载安装Tomcat步骤三&#xff1a;Tomcat配置环境变量步骤四&#xff1a;验证Tomcat配置是否成功步骤五&#xff1a;为IDEA配置Tomcat 步骤一&#xff1a;首先确认自己是否已经安装JDK jdk各版本通用安…...

Docker快速使用指南

docker pull ubuntu:22.04 //先拉取一个基础镜像&#xff0c;一般是操作系统创建一个Dockerfile&#xff0c;放在任意目录下&#xff0c;内容如下 # 使用 Ubuntu 22.04 作为基础镜像 FROM ubuntu:22.04# 设置环境变量&#xff0c;避免安装过程中出现交互提示 ENV DEBIAN_FRONT…...

【Project】基于Prometheus监控docker平台

一、设计背景 1.1项目简介 本项目旨在创建一个全面的容器化应用程序监控解决方案&#xff0c;基于Prometheus监控Docker平台上的各种服务。在当今的软件开发环境中&#xff0c;容器化技术已成为一种关键的工具&#xff0c;使应用程序能够更快速、可靠地交付和扩展。然而&…...

Binder通信协议

目录 一,整体架构 二,Binder通信协议 三&#xff0c;binder驱动返回协议 四&#xff0c;请求binder驱动协议 一,整体架构 二,Binder通信协议 三&#xff0c;binder驱动返回协议 binder_driver_return_protocol共包含18个命令&#xff0c;分别是&#xff1a; 四&#xff0c…...

使用 Postman 访问 Keycloak 端点

1. 引言 在本教程中&#xff0c;我们将首先快速回顾 OAuth 2.0、OpenID 和 Keycloak。然后&#xff0c;我们将了解 Keycloak REST API 以及如何在 Postman 中调用它们。 2. OAuth 2.0 OAuth 2.0 是一个授权框架&#xff0c;它允许经过身份验证的用户通过令牌向第三方授予访问…...

uniapp-X 对象动态取值

有个对象&#xff0c;例如 const data{age:12,list:[1,2,3,4]} 有个函数如下 export function getValueByPath(obj:UTSJSONObject, path:string):any {const current obj.getAny(path) as any;// 返回最终的值return current; } 期待 通过执行getValueByPath("xx.xx…...

建模软件Blender与Blender GIS插件安装教程

Blender&#xff08;blender.org - Home of the Blender project - Free and Open 3D Creation Software&#xff09;是一款功能强大的开源3D创作套件&#xff0c;它支持整个3D管道—建模、渲染、动画制作、模拟、渲染、合成和运动跟踪&#xff0c;甚至视频编辑和游戏制作&…...

数据解析与处理

数据解析与处理是数据科学、分析或开发中的核心步骤&#xff0c;涉及从原始数据中提取、清洗、转换和存储有效信息的过程。 一、数据解析 数据解析就是将原始数据&#xff08;如文本、二进制、日志、API响应等&#xff09;转换为结构化格式&#xff08;如表格、字典、JSON等&…...

强化学习概览

强化学习的目标 智能体&#xff08;Agent&#xff09;通过与环境&#xff08;Environment&#xff09;交互&#xff0c;学习最大化累积奖励&#xff08;Cumulative Reward&#xff09;​的策略。 数学抽象 马尔科夫决策过程&#xff08;MDP&#xff09; 收益 由于马尔科夫决…...

如何在netlify一键部署静态网站

1. 准备你的项目 确保你的静态网站文件&#xff08;如 HTML、CSS、JavaScript、图片等&#xff09;都在一个文件夹中。通常&#xff0c;项目结构如下&#xff1a; my-static-site/ ├── index.html ├── styles/ │ └── styles.css └── scripts/└── script.js…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...