《禅与 Objective-C 编程艺术》读书总结

Effective Objective-C 2.0 读书笔记 第 1 章 熟悉 Objective-C 第 2 章 对象消息运行时 第 3 章 接口和 API 设计 第 4 章 协议与分类 第 5 章 内存管理 循环引用 普通的两个变量互相引用 Block 循环引用 NSTimer 悬挂指针 持有释放不匹配 performselector CoreFoundation - Foundation try catch 其他 autoreleasepool blo 阅读详情

最近阅读了《禅与 Objective-C 编程艺术》这篇文章,奈何英文不算太好,而且看着好累,还好找到了中文版。读完了这篇文章,不管是对名词的解释、代码规范、还是编码技巧,都有所感悟,总结一下这篇文章需要记录的知识点。

1.常量

推荐使用常量来代替字符串字面值和数字,这样能够方便复用,而且可以快速修改而不需要查找和替换。常量应该用 static 声明为静态常量,而不要用 #define,除非它明确的作为一个宏来使用。

推荐:

static NSString * const ZOCCacheControllerDidClearCacheNotification = @"ZOCCacheControllerDidClearCacheNotification";

static const CGFloat ZOCImageThumbnailHeight = 50.0f;

不推荐:

#define CompanyName @"Apple Inc."

#define magicNumber 42

常量应该在头文件中以这样的形式暴露给外部:

extern NSString *const ZOCCacheControllerDidClearCacheNotification;

并在实现文件中为它赋值。

2.初始化

我们常常写 [[NSObject alloc] init] 这样的代码,Objective-C 的这个特性叫做 两步创建。这意味着申请分配内存和初始化被分离成两步,alloc 和 init。

  • alloc 负责创建对象,这个过程包括分配足够的内存来保存对象,写入 isa 指针,初始化引用计数,以及重置所有实例变量。

  • init 负责初始化对象,这意味着使对象处于可用状态。这通常意味着为对象的实例变量赋予合理有用的值。

alloc 方法将返回一个有效的未初始化的对象实例。每一个对这个实例发送的消息会被转换成一次 objc_msgSend() 函数的调用,形参 self 的实参是 alloc 返回的指针;这样 self 在所有方法的作用域内都能够被访问。 按照惯例,为了完成两步创建,新创建的实例第一个被调用的方法将是 init 方法。注意,NSObject 在实现 init 时,只是简单的返回了 self。

3.id 和 instancetype 区别

- (id)array;

- (instancetype)array;
+ (id)array {

    return [NSArray array];

}

+ (instancetype)array {

    return [NSArray array];

}

以上代码初始化数组,返回值分别是 id 和 instancetype

  • 返回值为 id 得到的返回类型是 id

  • 返回值为 instancetype 得到的返回类型是 NSArray *

总结一下 instancetype 优点:使那些非关联返回类型的方法返回所在类的类型。优点是能够确定对象的类型,帮助编译器更好的为我们定位代码书写问题。

4.isKindOfClass 和 isMemberOfClass 的区别

创建两个类:

  • Person 继承 NSObject

  • Student 继承 Person

BOOL bool1 = [teacher isKindOfClass:[Teacher class]];

BOOL bool2 = [teacher isKindOfClass:[Person class]];  

BOOL bool3 = [teacher isKindOfClass:[NSObject class]];

上面三个 BOOL 都为 YES!

BOOL bool1 = [teacher isMemberOfClass:[Teacher class]];  

BOOL bool1 = [teacher isMemberOfClass:[Person class]]; 

BOOL bool1 = [teacher isMemberOfClass:[NSObject class]];

上面第一个 BOOL 为 YES , 其余两个为 NO

所以 isKindOfClass 来确定一个对象是否是一个类的成员,或者是派生自该类的成员;isMemberOfClass 只能确定一个对象是否是当前类的成员

5.setter 和 getter 注意点

永远不要在 init 方法(以及其他初始化方法)里面用 getter 和 setter 方法,你应当直接访问实例变量。这样做是为了防止有子类时,出现这样的情况:它的子类最终重载了其 setter 或者 getter 方法,因此导致该子类去调用其他的方法、访问那些处于不稳定状态,或者称为没有初始化完成的属性或者 ivar 。记住一个对象仅仅在 init 返回的时候,才会被认为是达到了初始化完成的状态。

6.深入 Block

一些关键点:

  • block 是在栈上创建的

  • block 可以复制到堆上

  • block 会捕获栈上的变量(或指针),将其复制为自己私有的const(变量)。

如果 block 没有在其他地方被保持,那么它会随着栈生存并且当栈帧(stack frame)返回的时候消失。仅存在于栈上时,block对对象访问的内存管理和生命周期没有任何影响。

如果 block 需要在栈帧返回的时候存在,它们需要明确地被复制到堆上,这样,block 会像其他 Cocoa 对象一样增加引用计数。当它们被复制的时候,它会带着它们的捕获作用域一起,retain 他们所有引用的对象。

如果一个 block引用了一个栈变量或指针,那么这个block初始化的时候会拥有这个变量或指针的const副本,所以(被捕获之后再在栈中改变这个变量或指针的值)是不起作用的。(译者注:所以这时候我们在block中对这种变量进行赋值会编译报错:Variable is not assignable(missing __block type specifier),因为他们是副本而且是const的.具体见下面的例程)。

当一个 block 被复制后,__block 声明的栈变量的引用被复制到了堆里,复制完成之后,无论是栈上的block还是刚刚产生在堆上的block(栈上block的副本)都会引用该变量在堆上的副本。

最重要的事情是 __block 声明的变量和指针在 block 里面是作为显示操作真实值/对象的结构来对待的。

block 在 Objective-C 的 runtime(运行时) 里面被当作一等公民对待:他们有一个 isa 指针,一个类也是用 isa 指针在Objective-C 运行时来访问方法和存储数据的。在非 ARC 环境肯定会把它搞得很糟糕,并且悬挂指针会导致 crash。__block 仅仅对 block 内的变量起作用,它只是简单地告诉 block:

嗨,这个指针或者原始的类型依赖它们在的栈。请用一个栈上的新变量来引用它。我是说,请对它进行双重解引用,不要 retain 它。 谢谢,哥们。

如果在定义之后但是 block 没有被调用前,对象被释放了,那么 block 的执行会导致 crash。 __block 变量不会在 block 中被持有,最后… 指针、引用、解引用以及引用计数变得一团糟。

7.委托和数据源

本质上,委托代理模式仅需要代理方提供一些回调方法,即代理方需要实现一系列空返回值的方法。

不幸的是 Apple 的 API 并没有遵守这个原则,开发者也效仿 Apple 进入了一个误区。典型的例子就是 UITableViewDelegate 协议。

它的一些方法返回 void 类型,就像我们所说的回调:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath;

但是其他的就不是那么回事:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;

当委托者询问代理者一些信息的时候,这就暗示着信息是从代理者流向委托者而非相反的过程。这是概念性的不同,须用另一个新的名字来描述这种模式:数据源模式。

可能有人会说 Apple 有一个 UITableViewDataSouce protocol 来做这个(虽然使用委托模式的名字),但是实际上它的方法是用来提供真实的数据应该如何被展示的信息的。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

此外,以上两个方法 Apple 混合了展示层和数据层,这显的非常糟糕,但是很少的开发者感到糟糕。而且我们在这里把空返回值和非空返回值的方法都天真地叫做委托方法。

为了分离概念,我们应该这样做:

委托模式(delegate pattern):事件发生的时候,委托者需要通知代理者。

数据源模式(datasource pattern):委托者需要从数据源对象拉取数据。

强化学习:Distributed PPO (DPPO) 学习笔记 DPPO = Distributed + Proximal Policy Optimization Distributed:多个智能体并行训练 Proximal:限制策略更新幅度,确保稳定性 Policy Optimization:基于策略梯度的优化方法 核心思想:多个智能体并行探索环境,共享经验,通过裁剪策略更新确保训练稳定 阅读详情

相关推荐

时序约束实战:从setup/hold到时钟路径约束的深度解析

本文深度解析数字设计中的时序约束实战,重点探讨如何从setup/hold检查的核心原理出发,理解并应用时钟路径约束。文章通过剖析Path Requirement的计算逻辑,结合同频、倍频及异步时钟域等典型场景,提供了从解读时序报告到编写、调试SDC约束的系统方法,帮助工程师有效应对复杂SoC设计中的时序收敛挑战。

weixin_29291185的博客 105

《禅与Objective-C编程艺术》 (中文译本)

我参与翻译及后期校验的《禅与 Objective-C 编程艺术》 中文译本,https://github.com/oa414/objc-zen-book-cn我的其他项目: https://github.com/KevinHM/FunctionalReactiveProgrammingOniOS https://github.com/KevinHM/ios-good-practices-the...

hmxiao_1983的专栏 474

RT-Thread代码启动过程——以及 $Sub$ $main 与 $Super$ $main

我们找到系统复位的地方,可以往下单步跟踪。 ①从系统初始化开始执行,将函数地址赋给R0寄存器,跳转到R0地址执行并返回此处(BLX是带链接的跳转,即带返回的跳转)。 ②将main函数地址给R0,将函数地址赋给R0,跳转到R0地址执行,不返回(BX是跳转,不返回)。 ③跳转到了$Sub$$main。 【注:在 __CC_ARM 编译器环境下,使用了$Sub$$ 与$Super$ $ 的...

yang1111111112的博客 1万+

Objective-C 编程艺术

禅与 Objective-C 编程艺术 (Zen and the Art of the Objective-C Craftsmanship 中文翻译) 原文 https://github.com/objc-zen/objc-zen-bookGitbook 链接(包含 PDF, mobi, epub 格式): http://yourtion.gitbooks.io/objc-zen-book-

z1148278228的专栏 876

C51:PWM+舵机角度控制

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%.脉冲宽度调制通过占空比编码模拟信号一个周期内,高电平占据时长的百分比如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制。

qq_73379310的博客 3388

如何用libwebsocket库在stm32F407上实现websocket客户端?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1133

我看《禅与Object-C》

第一次在优快云上写博客,希望大家可以多多指点。 《禅与Object-C》这本书是公司大神给我推荐的,因为之前代码写的很不规范,可读性不够高,而且不够稳定。而《禅与Object-C》这本书很好的诠释了一些经常出现的代码问题。当然,我不是介绍这本书是有多么屌的,只是想简单写出我看完之后的感受,我个人认为只有把之前犯过的错记录下来并深刻反思,以后才不会犯同样的错误。

fb768652854的博客 643

Linux系统安全学习手册

Linux反弹shell Linux系统应急响应 Linux服务器安全加固 Linux下的用户、组和权限 Linux中的gcc Linux中su和sudo的用法和区别 Linux系统python2与python3共存 Linux中grep工具的使用 Linux中环境变量的设置 Linux中常见的150个命令(干货) Linux中编写Shell脚本 LNMP环境搭建Wordpress博客 LAMP环境搭建一个Discuz论坛 Linux运维比较常用的一些脚本 Linux系统中安装软

谢公子的博客 7532

电商下一个风口——C2M重塑制造业

过去十多年,电商行业走过了B2C和F2C等阶段,C2M将是业态进化的下一方向。上一轮消费互联网的革命,利用的是互联网和移动互联网技术,改变的是交易方式,提升的是交易效率。这一轮变革,利用的是5G、云、AI技术,在生产领域进行了一场产业革命,改变的是生产方式,提升的是制造效率。这一轮变革还有一个重大的不同,就是巨头入场。不仅阿里、京东、拼多多等互联网巨头在全力投入,制造业巨头同样入场厮杀。而二十年前...

AI天才研究院 8981

机器人轨迹规划——三次样条轨迹1(基于速度的求解方法)

三次样条轨迹是利用三次样条曲线来对给定的一系列点进行插值,从而得到一个光滑的轨迹。三次样条因为每段的多项式次数最高都是三阶的,所以可以得到2阶导数连续,也就是加速度连续的轨迹。假设给定了一系列的点q0q1q2qnq0​q1​q2​...qn​,以及每个点对应的参数t0t1t2tnt0​t1​t2​...tn​,计算一条三次样条曲线sts(t)st,该曲线通过给定的点q0q1q2qnq0​q1。

出门搔白首,若负平生志 1470

X线DR医学图像 --- DR医用滤线栅及摩尔纹详解 (二) 摩尔纹的产生机理

1,横向摩尔纹的表现 2,纵向摩尔纹的表现 3,摩尔纹在pitch = 143μm(注:pitch为采样间隔/周期)的FPD上的表现。 4,摩尔纹的危害(严重的影响了临床诊断) 5,摩尔纹对胸片肺部肺纹理的破坏 6,滤线栅的频率(滤线栅生产厂家的产品参数)。判断摩尔纹产生的重要依据之一 7,DR平板探测器的采样频率/空间极限分辨率 l.........

松下J27录放机 4981

《禅与Objective-C编程艺术》读书笔记(二)

五、Categories我们应该要在我们的 category 方法前加上自己的小写前缀以及下划线,比如- (id)zoc_myCategoryMethod。 这种实践同样被苹果推荐。这是非常必要的。因为如果在扩展的 category 或者其他 category 里面已经使用了同样的方法名,会导致不可预计的后果。实际上,实际被调用的是最后被实现的那个方法。如果想要确认你的分类方法没有覆盖其他实现的话,

王者归来之英雄有梦 1764

芯片设计|SoC芯片设计流程 与 软硬件协同设计

SoC通常被称作系统级芯片或者片上系统,作为一个完整的系统,**其包含了硬件和软件两部分内容**。这里所说的硬件指SoC芯片部分,**软件是指运行在SoC芯片上的系统及应用程序**。既然它是由软件和硬件组合而成,则在进行系统设计时,**就必须同时从软件和硬件的角度去考虑。**

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 1821

《禅与Objective-C编程艺术》读书笔记(一)

一、条件语句1.书写规范 条件语句体应该总是被大括号包围来避免错误,即使可以不用(比如,只有一行内容)。这些错误包括多加了第二行,并且误以为它是 if 语句体里面的。此外,更危险的可能是,如果把 if 语句体里的一行注释掉了,之后的一行代码会不知不觉成为 if 语句里的代码。因此,条件语句应该使用被大括号包围的方式去写。推荐: if (!error) { return success;

王者归来之英雄有梦 2002

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Effective Objective-C 2.0 读书笔记—— 接口与API设计

所有对象均要初始化。我们知道NSMutableSet的性质,当我们加入一个一模一样的元素时,set 里仍然只有一个对象,因为刚才要加入的那个数组对象和set 中已有的数组对象相等,所以set 并不会改变。的方法作为全能的初始化方法,然后就在剩下的初始化方法之中调用我们的全能初始化方法,当底层数据存储机制改变时,只需修改此 方法的代码就好,无须改动其他初始化方法。由于是继承于矩形类,我们在自定义正方形的初始化方法时,也要注意到我们也有可能调用父类的初始化方法,为了避免出现未知的问题,我们需要重写父类之中的。

aa2002aa的博客 1761

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

《Effective Objective-C 2.0》读书笔记——熟悉Objective-C

Objective-C在C语言基础上添加了面向对象特性,代码十分易读,但仍有许多微妙细节需要注意,而且还有许多容易为人所忽视的特性。 另一方面,有些开发者并未完全理解或是容易滥用某些特性,导致写出来的代码难于维护且不易调试。

XY_Mckevince的博客 2098

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

《objective-c基础编程》读书笔记

第二章 对C的扩展1.#import是GCC编译器提供的,Xcode在编译Objective-C, C和C++程序时都会使用它。#import可保证头文件只被包含一次; 2.Cocoa的组成部分有Foundation和Application Kit(AppKit)框架; 3.Foundation框架处理的是用户界面之下的层(layer)中的特性; 4.”NS”前缀是因为NeXT Softwar

奔向火星的博客 659

Effective Objective-C 2.0 读书笔记—— objc_msgSend

消息其实就是由接受者,选择子和方法参数所构成,给对象发送消息其实就是相当于在该对象之中调用方法。通过,方法的调用变得非常灵活,可以在运行时根据对象和方法选择器找到并执行相应的方法。这个机制为我们后面学习的动态方法解析、消息转发、方法交换等强大的特性做了铺垫。

aa2002aa的博客 1862

Effective Objective-C 2.0 读书笔记——大中枢派发

队列特定数据允许你将任意数据(以键值对形式)关联到一个特定的 GCD 队列上。这个数据就像“标签”一样,可以让你在执行任务时知道当前任务属于哪个队列。

aa2002aa的博客 1829

Effective Objective-C 2.0 读书笔记——关联对象

暑假的任务是学习Effective Objective-C 2.0书上的相关内容,今天终于开始着手写读书笔记,希望能够在寒假多发两篇吧其实关联对象一定程度上是等同于在子类之中添加属性的,只是相对来说,使用关联对象会比写一个子类并且调用其中的方法更加节约资源一点,本质上其实就给我们提供了一个动态修改的空间,更加的灵活。

aa2002aa的博客 1836

Effective Objective-C 2.0 读书笔记—— 消息转发

在前面我学习了关联对象和的相关内容,初步了解了OC的动态机制,在我们的的执行操作之中,我们提到了,如果对象接受了无法解读的消息之后,就会进行消息转发。那么什么消息可以被理解呢?最基本的就是,我们的程序要实现对应的方法,由于OC动态语言的特性,我们在编译期的时候仍可以在类之中添加方法,所以当对象接受到无法解析的消息时就会启动消息转发机制消息转发一共由两种情况动态方法解析(Dynamic Method Resolution)

aa2002aa的博客 2015

Objective-C基础教程读书笔记(1)

1.第1章启程 本书除了介绍Objective-C语言,还会介绍苹果公司为其提供的工具包Cocoa(针对OS X系统)和Cocoa Touch(针对iOS系统)。它们都是用Objective-C语言编写的,里面分别包含了OSX和iOS系统的所有用户界面元素和其他所有相关内容。学会了Objective-C之后,你就可以用Cocoa来开发功能完备的项目。 1.1.预备知识 读者在阅读本书之前,应

默然说话 2814

Objective-C语言必看书籍推荐

Objective-C,通常写作ObjC或OC和较少用的Objective C或Obj-C,是扩充C的面向对象编程语言。它主要使用于Mac OS X和GNUstep这两个使用OpenStep标准的系统,而在NeXTSTEP和OpenStep中它更是基本语言。 以下书籍都是现在业内主流的OC语言好书,同步收录在顶书,通过下面网址进入,实时读书: 顶书-提升IT技术和认知​i-book.top Objective-C高级编程 本书在苹果公司公开的源代码基础上,深入剖析了对应用于内存管理的ARC 以及

reggieding的博客 1586

《Objective-C 高级编程》读书笔记之 GCD

前言 本文作为《Objective-C 高级编程》读书笔记的第三篇,也是最后一篇,给大家带来的是关于 Grand Central Dispatch (GCD) 的知识点总结。 概念 Grand Central Dispatch (GCD) 是异步执行任务的技术之一。开发者只需要定义想执行的任务并追加到适当的 Dispatch Queue 中,GCD 就能生成必要的线程并计划执行任务。由于

冷小G的技术博客 633

Objective-C基础教程读书笔记

Objective-C基础教程是我买的第一本关于iOS开发的书籍,今天拿出来重新阅读,重新学习一遍。

adults的博客 734

《Objective-C高级编程 iOS与OS X多线程和内存管理》读书笔记

iOS高级编程-iOS与OS+X多线程和内存管理 第一章:自动引用计数 自己生成的对象,自己所持有。 非自己生成的对象,自己也能持有 不再需要自己持有的对象时释放 非自己持有的对象无法释放 对象操作 Objective-C方法 生成并持有对象 alloc/new/copy/mutableCopy等 持有对象 retain 释放对象 release 废弃对象 deal...

极客学伟的技术分享社区 867
上一篇: SDWebImage 源码阅读(四)
下一篇: 《Effective Objective-C 2.0》读书笔记
mayan29
博客等级 码龄11年 13粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值