Objective-C内存管理、block与GCD

内存管理
  • 引用计数:引用计数表维护对象的引用数
  • autorelease:添加到最内层的AutoReleasePool对象列表,在销毁AutoReleasePool时释放列表内对象
  1. 非alloc/new/copy/mutableCopy开始的方法返回的对象,自动注册到autoreleasepool,但是如果返回值被强应用,则编译器会优化为不需要注册到autoreleasepool。
  2. 对象指针的指针,默认指向的对象为__autorealease,因为原则上非自己创建的对象不应由自己持有。如NSError **等价于 NSError * __autorelease *
  • ARC使用规则
  1. 不能使用retain/release/retainCount/autorelease
  2. 不能使用NSAllocateObject/NSDeallocateObject
  3. 必须遵守内存管理方法的命名规则

alloc/new/copy/mutableCopy开头的方法必须返回对象
init开头的方法要求更严格,必须是实例方法,返回的对象必须是id、所在的类、该类的超类或子类。返回的对象不会注册到autoreleasepool。

  1. 不要显示调用dealloc
  2. 使用@autoreleasepool代替NSReleasePool

MRC也应该用@autoreleasepool

  1. 不能使用NSZone

MRC也不要用,其实系统会忽略

  1. 对象变量不能作为C语言结构体成员

C语言没法管理结构体上的成员的生命周期

  1. 需要显示转换id和void *

__bridge转换,不发生所有权的转换
__bridge_retained,转换后的变量也持有对象
__bridge_transfer,被转换的变量所持有的对象赋值给目标变量后释放
对应Core Foundation的转换CFBridgingRetain/CFBridgingRelease

void *p = (__bridge_retained void *) obj;
id obj = (__bridge_transfer id) p;
  • 属性@property
    assign/copy/retain/strong/unsafe_unretained/weak

在生命类成员变量时,和属性声明的不一样时会有编译错误,当然现在一般也不需要手动写生成类成员变量,一般都是直接用@property自动生成。

  • ARC实现
    1 . strong,在作用域结束时release,对于非alloc/init/copy方法的对象,本来是通过objc_autoreleaseReturnValue(obj)注册到autoreleasepool,但是在被strong引用时,会通过调用objc_retainAutorealseReturnValue(obj)来引用对象,这时编译器就判断为不需要添加到autoreleasepool。
  1. weak,引用对象时记录到weak表中,在对象释放时,吧weak表中指向对象的变量置空。使用weak变量时会自动生成临时变量,对象被添加到autorealeasepool。
id __weak o = obj;
NSLog(@"1 %@", obj);   // 添加一次
NSLog(@"2 %@", obj);   // 再添加一次

// 改为下面可以避免添加到autoreleasepool
id __weak o = obj;
id tmp = o;
NSLog(@"1 %@", tmp);  
NSLog(@"2 %@", tmp);   

3、autorealease,相当于MRC的手动调用autorealease方法

Blocks

Blocks是C语言的扩展功能:带有自动变量的匿名函数。
格式:

^int (int count) {return count + 1;}  // 完整格式
^(int count) {printf("%d", count)} // 无返回值
^{printf("test")} // 无返回值
// block类型定义
typedef int (^blk_t) (int);
  • 截获自动变量

普通变量的值未截获时的值,不能修改
__block变量可以被block修改值
不支持截获数组,需要的话转为指针

  • block的实现

block实质上是会生成一个Objective-C的对象,截获的自动变量会保存在对象中,__block变量会生成__Block_byrefer_val结构体,存放到block中,通过其中的__forwarding间接访问实际变量,当block被复制到堆时,如果栈上的__block变量也会被复制到堆。

  • 有三种区域的block
    全局Block:在全局变量处定义或者在Block不需要截获自动变量时
    栈Block:除全局Block之外,定义时默认都是栈Block
    堆Block:Block作为函数返回值时会被复制到堆,使用copy方法会复制到堆,将Block赋值给strong类型的变量,或者赋值给Block类型的成员变量时会复制到堆。

向方法传递Block时不会自动复制到堆,除了下面两种方法:

  1. Cocoa框架中代用usingBlock的方法
  2. GCD的API
    对全局Block进行copy没有任何作用
  • block循环应用
  1. 通过__weak解决
  2. MRC时通过__block解决,但是需要在Block执行完后置空,在置空之后才会释放。这是因为__block指向的对象复制到堆时不会被retain。
GCD
  • 两种队列:Serial DispatchQueue和Concurrent Dispatch Queue

一个Serial Dispatch Queue生成并使用时会创建一个新线程,需要防止过多线程
Dispatch Queue必须自己release,并且对于非create方法返回的queue要retain

  • dispatch_set_target_queue
  1. 变更队列的执行优先级
  2. 目标队列可以成为原队列的执行阶层(多个queue被设置到某个target时)
  • dispatch_after

并不是在指定的时间后执行,二是在指定的时间后添加到queue

  • Dispatch Group

在希望多个处理全部执行之后,再执行其他处理时使用

  • dispatch_barrier_async

等待所有位于barrier函数之前的操作执行完毕后执行,并且在barrier函数执行之后,barrier函数之后的操作才会得到执行

  • dispatch_async

在处理执行结束之前,函数不会返回。注意死锁问题,如下:

dispatch_queue_t queue dispatch_get_main_queue();
dispatch_async(queue, ^{
        dispatch_sync(queue, ^{});
})
  • dispatch_apply

按指定次数讲block追加到指定的queue中并等待处理完毕。

  • dispatch_suspend / dispatch_resume

暂停或恢复queue对执行的处理,对于已处理或正在处理的没有影响

  • Dispatch Semaphore

信号量,wait方法计数未0时等待,计数>=1时不等待而减去1。signal方法加1

dispatch_semaphore_t semaphore = dispatch_semaphore_create(2); // 创建数量为2的信号量
dispatch_semaphore_wait(semaphore, time); // 信号量-1
dispatch_semaphore_signal(semaphore); // 信号量+1

  • dispatch_once

保证应用程序执行过程中只执行一次处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,395评论 8 265
  • 自动引用计数 内存管理&引用计数 自己生成的对象,自己所持有 非自己生成的对象,自己也能持有 无法释放非自己持有的...
    angry_zxy阅读 1,052评论 0 4
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,106评论 1 32
  • OC语言基础 1.类与对象 类方法 OC的类方法只有2种:静态方法和实例方法两种 在OC中,只要方法声明在@int...
    奇异果好补阅读 4,280评论 0 11
  • 有人说时间是愈合伤口最好的良药,但渐渐地发现有些人,有些事随着时间的流逝,越发变的清晰。这或许都怪我们记性太好,...
    若相惜必相守阅读 317评论 0 0