Book - Objective-C高级编程

iOS通讯录操作全面封装:Objective-C对象化访问无需再写C语言代码 自iOS 9起,Apple引入了Contacts框架,作为对老旧Address Book C API的现代化替代。该框架采用Objective-C的面向对象设计,提供类型安全、语义清晰的接口,极大提升了开发效率与代码安全性。系统错误码分散且不易理解,建议定义枚举:并在发生错误时构造NSError:除了静态属性外,SLContact还需具备一定的“智能”行为能力,使其成为一个真正意义上的领域模型对象。这类方法不改变状态,但能辅助业务逻辑判断与展示控制。 阅读详情

1.1什么是自动引用计数


关于ARC技术,最重要的还是下面这一点:

++在LLVM编译器中设置ARC为有效状态,就无需再次键入retain或者是release代码。++

1.2 内存管理/引用计数


1.2.1 概要

OC中的内存管理,也就是引用计数。可以用开关灯房间的案例来说明:

假设办公室照明设备只有一个。上班的人进入办公室需要照明,所以把灯打开。而队对于下班离开办公室的人来说,已经不需要照明了,所以把等关掉。若是很多上下班,每个人都开灯或者关灯,那么办公室的情况又将如何呢?最早下班的人关灯,那么办公室岂不是一片黑暗。

解决这个问题的办法是使办公室还有至少一个人的情况下保持开灯状态,无人的时候保持关状态。
1. 最早进入办公室开灯
2. 之后进入办公室的人,需要照明
3. 下班离开办公室的人,不需要照明
4. 最后离开办公室的人关灯(此时已无人需要照明)

根据计数功能来计算 ”需要照明的人数”

  1. 第一个人进入办公室,办公室的计数为1。计数:1
  2. 之后进入办公室的人,叠加1。计数:2
  3. 每当人有人下班离开,减去1。计数:1
  4. 最后离开办公室,减去1。计数:0,因此要关灯。

在OC中,”对象” 相当于办公室的照明设备。

  1. 开灯 –> 生成对象
  2. 需要照明 –> 持有对象
  3. 不再需要照明 –> 释放对象
  4. 关灯 –> 废弃对象

1.2.2 内存管理的思考方式
  • 自己生成的对象,自己持有。
  • 非自己生成的对象, 自己也能持有。
  • 不再需要自己持有的对象时释放。
  • 非自己持有的对象无法释放。
对象操作Objective-C方法
生成并持有对象alloc/new/copy/muetableCopy等方法
持有对象retain 方法
释放对象release 方法
废弃对象dealloc 方法
自己生成的对象,自己持有

上面出现了很多 “自己” 一词。本文所说的 “自己” 固然对应上面提到的 “对象使用环境”,但将之理解为编程人员 “自身” 也是没错的。

下面写出了自己生成并持有对象,我们使用alloc方法:

//自己生成并持有对象
id obj = [[NSObject alloc] init];

copy方法利用基于NSCopying方法约定,由各类实现copyWithZone:方法生成并持有对象的副本。与Copy方法类似,mutableCopy方法利用基于NSMutableCopying方法约定,由各类实现mutableCopyWhitZone:方法生成持有对象的副本。

这些方法生成的对象,虽然是对象的副本,但同alloc、new方法一样,在 “自己生成并持有对象” 这点上没有改变。

非自己生成的对象, 自己也能持有
//取得非自己生成并持有的对象
id obj = [NSMutableArray array];

上述源码中,NSMutableArray类对象被赋给变量obj,但变量obj自己并不持有改对象。使用retain方法可以持有对象。

//持有对象
[obj retainl];
不再需要自己持有的对象时释放

自己持有的对象,一旦不再需要,持有者有义务释放该对象。释放使用release方法。

//自己生成并持有对象
id obj = [[NSObject alloc] init];

//释放
[obj release];
对象的持有与非持有原理

用 alloc/new/copy/mutableCopy 方法生成并持有的对象,或者用 retain 方法持有的对象,一旦不再需要,务必要用 release 方法进行释放。

如果要用某个方法生成对象,并将其返还给该方法的调用方,那么它的源码又是怎么样的。

+ (NSObject *) allocObject {
    //自己生成并持有对象
    id obj = [[NSObject alloc] init];
    //自己持有对象
    retain obj;
}

原封不动地返回用 alloc 方法生成并持有对象,就能让调用方也持有该对象。

// 取得非自己生成并持有的对象???
id obj1 = [NSObject allocObject];

allocObject与用alloc方法生成并持有对象的情况完全相同,所有使用allocObject方法也就意味着 “自己生成并持有对象”

那么,调用 [NSMutableArray array] 方法使取得的对象存在,但是自己又不持有对象,又是怎么实现的呢?

- (id)object {

    //自己生成并持有对象
    id  obj =  [[NSObject alloc] init];

    //使对象在超出指定的生成范围时能够自动并正确地的释放
    [obj autorelease];

    //返回对象
    return obj;
}

上例中,我们使用了 autorelease 方法。用该方法,可以使取得的对象存在,但是自己不持有对象。

这样的好处就是,我们可以不用去手动去管理通过此方法 生成的对象 的释放。

autorelease 提供这样的功能,是对象在超出指定的生成范围时能够自动并正确地释放(调用release方法)

release 和 autorelease 的区别

使用NSMutableArray类的array类方法等可以取得谁都不持有的对象,这些方法都是通过 autorelease 而实现的。此外 ++根据命名规则,这些取得谁都不持有的对象的方法名不能以 alloc/new/copy/mutableCopy 开头,这点需要注意。++

无法释放非自己持有的对象

对于用 alloc/new/copy/mutableCopy 方法生成并持有的对象,或者是用 retain 方法持有的对象,由于持有者都是自己,所以在不需要该对象时需要将其释放。

而由此以外所得到的对象绝对不能释放。倘若在应用程序中释放了非自己所持有的对象会造成崩溃。

例如自己生成并持有对象后,在释放完后,再次释放。(重复调用release);

或者是在 “取得对象的存在,但是自己不持有对象” 时释放。

都会到导致应用程序崩溃!因此绝对不要释放非自己持有的对象!

以上五项内容,就是 “引用计数式内存管理” 的思考方式。

1.2.3 alloc/reatin/release/dealloc 实现(翻墙失败,过些天再细究)

我们来看看 GUNstep 源代码中 NSObject 类的的 alloc 类方法。

id obj = [NSObject alloc];

上述调用 NSObject 类的 alloc 类方法在 NSObjecr.m 源代码中的实现如下。

+ (id) alloc
{
   return [self allocWithZone: NSDefaultMallocZone()]; 
}
+ (id) allocWithZone:(NSZone *)z
{
    return NSAllocateObject(self,0,z);
}

通过 allocWithZone: 类方法调用 N\NSAllocateObject 函数分配对象。下面我们查看 NSAllocateObject 函数.

struct obj_layout {
    NSUInterger  retained;
}
inline id NSAllocateObject (Class aClass, NSUInterger extraBytes, NSZone *zone) {

    int size = 计算容纳对象所需内存大小;
    id new = NSZoneMalloc(zone, size);
    memset(new, 0, size);
    new = (id)&((struct obj_layout *) new)[1];
}

NSAllocateObject 函数通过调用 NSZoneMalloc 函数来分配存放对象所需的内存空间,之后将改内存空间置0,最后返回作为对象而使用的指针。

image

以下是去掉 NSZone 后简化了源代码:

struct obj_layout {
    NSUInterger  retained;
}
+ (id) alloc {
    int size = sizeof(struct obj_layout) + 对象大小;
    struct obj_layout *p = (struct obj_layout *)calloc(1, size);
    return (id)(p+1);
}

alloc 类方法用 struct obj_layout 中的 retained 整数来保存引用计数,并将其写入对象内存头部,该对象内存全部置0后返回。

以下用图来展示有关 GUNstep 的实现,alloc类方法返回对象,如图

image

对象的引用计数可通过 retainCount 实例方法来取得。

id obj = [NSObject alloc];
NSLog(@"retainCount=%d", [obj retainCount]); // => 1

执行alloc后对象的 retainCount 是 “1”。下面通过 GUNstep 的源代码来确认。

- (NSUInteger)retainCount {
   return NSExtraRefCount(self) + 1; 
}
inline NSUInterger NSExtraRefCount(id  anObject) {
    return ((struct obj_layout *) anObject)[-1].retained;
}

由对象寻址找到对象内存头部,从而访问其中的retained变量。如图:

image

1.2.4 autorelease

autorelease 就是自动释放。这看上去很像ARC,但实际上它更类似于C语言中的自动变量(局部变量)的特性。

{
    int a;
}
/*
 因为超出变量作用域,自动变量 "int a" 被废弃,不可再访问
*/

autorelease 会像 C 语言的自动变量那样来对待对象实例。当超出其作用域(相当于变量作用域)时,对象实例的 release 实例方法被调用。另外,同 C 语言的自动变量不同的是,编程人员可以设定变量的作用域。

autorelease 的具体使用方法如下:

  1. 生成并持有 NSAutoreleasePool 对象
  2. 调用已分配对象的 autorelease 实例方法
  3. 废弃 NSAutoreleasePood 对象

NSAutoreleasePool 对象的生命周期

NSAutoreleasePool 对象的声明周期相当于 C 语言变量的作用域。对于所有调用过 autorelease 实例方法的对象,在废弃 NSAutoreleasePool 对象时,都将调用 release 实例方法。如上图。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

id obj = [[NSObject alloc] init];

[obj autorelease];

[pool drain];

“[pool drain]” 等同于 “[obj release]”。

在 Cocoa 框架中,相当于程序主循环的 NSRunLoop 或者在其他程序可运行的地方,对 NSAutoreleasePool 对象进行生成、持有和废弃处理。因此,应用程序开发者不一定非得使用 NSAutoreleasePool 对象来进行开发工作。

意思就是我们不一定需要去管理 NSAutoreleasePool。

这里写图片描述

尽管如此,但在大量产生 autorelease 的对象时,只要不废弃 NSAutoreleasePool 对象,那么生成的对象就不能被释放,因此有时会产生内存不足的现象。

典型的例子:读入大量图像的同时改变尺寸。图像文件读入到 NSData 对象,并从中生成 UIImage 对象,改变该对象尺寸后生成新的 UIImage 对象。这种情况下,就会大量生成 autorelease 对象。

for (int i = 0; i < 图像数; ++i){
    /*
    读入图像
    大量产生 autorelease 对象
    由于没有废弃 NSAutoreleasePool 对象
    最终导致内存不足
    */
}

在此情况下,有必要在适当的地方生成,持有或者废弃 NSAutoreleasePool 对象。

for (int i = 0; i < 图像数; ++i){

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    /*
    读入图像
    大量产生 autorelease 对象
    */

    [pool drain];
}

另外,Cocoa 框架中也有很多类方法用于返回 autorelease 的对象。比如 NSMutableArray 类的 arrayWithCapacity 类方法。

id array = [NSMutableArray arrayWithCapacity:1];

此源代码等同于以下源代码

id array = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
1.2.5 autorelease 实现 - GUNstep是如何实现的
[obj autorelease];

此源代码调用 NSObject 类的 autorelease 实例方法。

GUNstep实现:

- (id) autorelease {
    [NSAutoreleasePool addObject:self];
}

autorelease 实例方法的本质就是调用 NSAutoreleasePool 对象的 addObject 类方法。

这里写图片描述

+ (void) addObject:(id)anObj {

    NSAutoreleasePool *pool = 取得正在使用的 NSAutoreleasePool 对象;

    if (pool != nil) {
        [pool addObject: anObjc];
    }else{
        NSLog(@"NSAutoreleasePool 对象非存在状态下调用 autorelease")
    }
}

addObject 类方法调用正在使用的 NSAutoreleasePool 对象的 addObject 实例方法。

如果嵌套或者持有 NSAutoreleasePool 对象,理所当然会使用最内侧的对象。

- (void) drain {
    [self dealloc];
}
- (void) dellloc {
    [self emptyPool];
    [array release];
}
- (void) emptyPool {
    for (id obj in array){
        [obj release];
    }
}

虽然调用了好几个方法,但是可以确定对于数组中的所以对象都调用了 release 实例方法。

1.2.6 苹果的实现
Objective-C 圣经 Epub版 Objective-C 开发圣经级别的书籍的epub版 立即下载

相关推荐

Objective-C高级编程†

Objective-C高级编程,对入门的iOS开发者有很大的帮助,可以更深入的了解Objective-C。

Objective-C:001

1.#import 是一个预处理指令;同一个文件,无论使用它导入多少次,都是一次;只需要直接包含就可以,其他什么都不用做。 2.Foundation 这是一个框架,提供基本功能;Foundation.h包含了框架中所有的头文件 3.main函数 它的参数用来让用户运行程序时传递数据给程序 4.@autoreleasepool 自动释放池,可写可不写,关乎内存管理,待续 5.NSLog函数 用于向控制台输出信息,能输出比较多的信息比如执行代码的时间和进程编号等;会自动换行,但如果自己写了\n,它的自动换行就会

weixin_50970194的博客 250

Objective-C编程全解 第3版 中文版

Objective-C编程全解 第3版 清晰完整中文版,多次再版的圣典

《Objective-C高级编程:iOS与OS X多线程和内存管理》 一 Blocks模式&GCD

一、Blocks摘要 Blocks:带有自动变量(局部变量)的匿名函数。 匿名函数:不带有名称的函数。 int func(int cout); //声明名称为func的函数 int result = func(10); // 调用该函数,必须使用该函数的名称 // 若像下面这样,使用函数指针来代替直接调用函数,那么不知道函数名也可调用 int result = (*funptr)(10); // 但使用函数指针也仍需知道函数名称,在赋值给函数指针时,若不使用想赋值的函数的名称,就无法取得该函数的地址

努力进阶的小菜鸟 892

Objective-C高级编程 iOS与OS X多线程和内存管理_Objective-C_ios_

Objective-C高级编程 iOS与OS X多线程和内存管理.pdf

GUNStep 开发类库API

GUNStep 开发类库API ObjectiveC

[OC学习笔记]Grand Central Dispatch

继续学习GCD

weixin_52192405的博客 3558

RYU+mininet——RYU

1. 使用RYU做mininet的控制器 1.1 RYU介绍与安装 RYU是一款基于python的控制器,你可用Ryu实现各种想要实现的网络功能,它可以下发或接收流表进行各种路由运算。 建议使用高版本的Ubuntu系统安装ryu,否则会有各种错误,安装过程比较简单,如下: apt install gcc libffi-dev libssl-dev libxml2-dev libxslt1-...

qq_34415266的博客 1万+

《Objective-C 高级编程》干货三部曲(二):Blocks篇

这一章讲解了Block相关的知识。因为作者将Objective-C的代码转成了C++的代码,所以第一次看的时候非常吃力,我自己也不记得看了多少遍了。 这篇总结不仅仅只有这本书中的内容,还有一点在其他博客里看过的Block的相关知识,并加上了自己的理解,而且文章结构也和原书不太一致,是经过我的整理重新排列出来的。 先看一下本文结构(Blocks部分): 需要先知道的 Objective-C 转 C...

weixin_34163741的博客 334

储能逆变器动态无功补偿:从原理到算法实现

本文深入解析了储能逆变器动态无功补偿的核心原理与算法实现。通过四象限运行与解耦控制技术,储能逆变器可在充放电的同时,快速、精准地调节无功功率,有效提升电网电能质量与功率因数。文章详细阐述了从相位调节、容量限制到PI控制算法的完整技术路径,并结合工程实践,探讨了其在光伏/储能系统中的协同控制策略与进阶应用价值。

weixin_29216353的博客 207

[RK3588-Android12] 深入解析USB Type-C PD充电功能的DTS配置与内核驱动修改

本文深入探讨了在RK3588 Android12平台上禁用USB Type-C PD充电功能的实现方法。通过分析设备树(DTS)配置与内核驱动(TCPM框架)的联动修改,详细解读了如何通过添加`pd-disable`属性及修改`tcpm.c`驱动代码,使Type-C端口绕过PD协议协商,仅工作在传统电源模式,以满足工控等特定场景对供电稳定性和成本控制的需求。

9o8p7i6u5y的博客 994

Blocks —— 《Objective-C高级编程 iOS与OS X多线程和内存管理》

Block相关知识以及Block在OC中的使用分析,了解了一点C++的特有功能

XY_Mckevince的博客 3921

人工智能在高中教育中的应用现状剖析与挑战应对

人工智能在高中教育中的应用现状剖析与挑战应对

燕鹏 1339

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

基于YOLOv11的手术器械计数系统:从数据集构建到Web应用部署

m2cai16-tool数据集:包含15种腹腔镜手术器械的标注图像Cholec80数据集:包含80个胆囊切除手术视频,标注了7种器械SurgicalTools数据集:包含超过10,000张手术器械图像,涵盖21类常见器械手术剪(Scissors)止血钳(Hemostat)持针器(Needle Holder)手术刀(Scalpel)镊子(Forceps)拉钩(Retractor)吸引器(Suction)

YOLO 396

爆肝5万字❤️Open3D 点云数据处理基础(Python版)

本文为Open3D 点云数据处理基础教程(Python版),小白也能轻松上手!还等什么呢,学起来!

孙悟空 13万+

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

【20】方案管理器

方案管理器是Excel中一个非常强大且灵活的工具,适合用于多情景分析和比较。在复杂的决策过程中,它可以帮助用户快速管理和评估不同变量组合下的结果,从而优化决策过程。

学习,输出==》再学习再输出 1585

Objective C KVC编程

KVC概述 KVC是KeyValue Coding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。 当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术。 使用KVC、KVO的优势 通过规定了一组通用的Cocoa命名法则、调用规则等,实现了如下功能: 1

KindAzrael的专栏 2333

2024-江苏科技大学-模拟-动态接触角,模拟液滴撞击,comsol软件模拟。

相反,其对液滴粘度和平衡接触角的变化基本不敏感。重力势能的影响显著受过程参数调节,随着液滴直径和密度的增加而增加,而随着初始液滴速度和表面张力系数的增加而减小。通过考虑形状因子和粘度修正因子,可以准确定义表面能和粘性耗散能,使得所提出的半经验修正勺状模型表现出良好的性能,在所有65个研究案例中,液滴最大铺展长度因子(βmax)和中心厚度(h)的相对误差基本分别落在5%和10%的区间内。重力势能的影响受过程参数显著调节,随液滴直径和密度的增大而增大,随液滴初始速度和表面张力系数的增大而减小。

qq_15963745的博客 512

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

objc-zen-book-cn翻译幕后:如何将世界级编程智慧带给中文开发者

ObjC Zen Book 中文翻译项目(objc-zen-book-cn)是一项致力于将世界级 Objective-C 编程智慧带给中文开发者的开源翻译工程。这个项目不仅是技术文档的跨语言转换,更是一次编程文化的深度传播,让中国开发者能够无障碍地汲取国际顶尖的 Objective-C 编程经验与哲学思想。 [![ObjC Zen Book 中文翻译项目标志](https://raw.gitco

gitblog_00697的博客 870

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

探秘《Objective-C Zen Book 中文版》:打造 iOS 和 macOS 开发新体验

探秘《Objective-C Zen Book 中文版》:打造 iOS 和 macOS 开发新体验 在编程世界中,找到一本深入浅出、实战性强的技术书籍是提升技能的关键。如果你正在寻找有关 Objective-C 的优质资源,那么不妨了解一下这个项目:。 项目简介 《Objective-C Zen Book 中文版》是由 Yourtion 翻译的开源项目,它基于原版 Objective-C Zen ...

gitblog_00051的博客 1083

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Objective-C高级编程——KVC(一)

【基本概念】 1.键值编码是一个用于间接访问对象属性的机制,使用该机制不需要调用存取方法和变量实例就可访问对象属性。 2.键值编码方法在OC非正式协议(类目)NSKeyValueCoding中被声明,默认的实现方法由NSObject提供。 3.键值编码支持带有对象值的属性,同时也支持纯数值类型和结构。非对象参数和返回类型会被识别并自动封装/解封。 【键值访问】   键值编码中

乞力马扎罗的雪CYF的博客 2540

objective-c之struct

// // main.m // struct // // Created by wu jianhua on 16-8-3. // Copyright (c) 2016年 wujianhua. All rights reserved. // #import struct Books { NSString *title; NSString *author; NSS

云守护的专栏 1786

禅与 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-cn/ (感谢 yourtion 整理 ) 前言 Swift贡献给社区作者关于中文翻译 条件语句 尤达表达式nil 和 BOO

銟麯的博客 1290

Objective-C语言的迭代器

当然,有时我们需要为自定义对象实现自己的迭代器。下面我们来创建一个简单的迭代器类。我们首先定义一个Book类,然后创建一个集合类,以及一个迭代器类。// Book.h@end// Book.m@end@end接下来实现类,使其可以遍历中的书籍。@end现在我们可以使用自定义的迭代器类来迭代书籍集合。Book```

2501_91391043的博客 889
上一篇: 编写高质量iOS与OS X代码的52个有效方-Effective Objective-C 2.0阅读笔记
下一篇: 内存管理(一) - 引用计数式的理解
Code_浅蓝
博客等级 码龄11年 28粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值