-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgoon.ios.txt
171 lines (89 loc) · 10 KB
/
goon.ios.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
ARC:
只能管理OC 对象, 不能管理通过malloc申请的内存
常用规则:
不能调用跟引用计数相关的方法(retain,release,autorelease,retainCount,也不能使用这些函数的selecter(例如@selecter(retain)))
ARC中禁止使用NAAutoReleasePool,而使用新语法@autoreleasepool来管理自动释放池
手动管理内存情况:
id pool=[[NSAutoreleasePool alloc] init]
/* 一些操作
不可使用break、return、goto等,否则有可能造成对象无法被成功释放*/
[pool release]
新语法:
@autoreleasepool{
/*一些操作
可以使用break、return、goto等,在运行到@autoreleasepool 块外的时候才进行对象释放*/
}
@autoreleasepool在非ARC模式下也能使用,并且使用@autoreleasepool比使用NSAutoReleasePool性能更好,效率更高,所以无论是否使用ARC都推荐使用这种新语法
在ARC中,未指定初始值的变量(包括局部变量)都会被初始化为nil,但是对于_autoreleasing和_unsafe_unretained修饰的变量来说,初始值是未定的
而对象以外的变量的初值和以前是一样的
方法族:《Object-C编程全解》P91
使用名称中包含 new、copy、mutableCopy、alloc、init、retain这些方法是就会获取这个对象的所有权,只有使用release或autorelease才能释放这个对象的所有权
这些规定被叫做所有权策略,即对象实例该由谁释放,由编程逻辑决定
由于ARC允许混合链接手动内存管理和自动内存管理的代码,所以针对到底哪个方法同对象的生成和复制相关,不能仅凭方法名区分,而需要定义能够让编译器明确区分的方法,
同对象生成相关的方法集合叫做方法族
一个方法要属于某个方法族,需满足返回值和方法的类别方面的要求(具体??为对应对象类?),也需满足以下命名规则
1、选择器同方法族名相同(开头的_可以忽略)
_1、或选择器的名字由方法族名加上非小写字母开头的字符串构成
目前一共定义了5个方法族:
alloc方法族
copy方法族
mutableCopy方法族
new方法族
以上4种表示调用者对被创建的对象拥有所有权,返回的对象必须是可以被retain的
可以是类方法也可以是实例方法,需要将对象所有权返回给调用端,由调用的release生成的对象,
而如果你想有调用端release一个方法返回的对象,而这个方法的名字却不以上述关键字开头,ARC可能不会释放这个对象, 而造成内存泄漏
init方法族
必须被定义为实例方法,一定要返回id类型或父子类的指针
必须要严格遵守内存管理相关的函数命名规则,例如给一个换行的方法命名为newLine可能造成误释放
ARC中的dealloc
ARC中对象被释放的时候,对象的dealloc函数也会被调用,与手动管理不同的是,要被释放的对象呗另一个对象保持的情况下,ARC会自动进行释放,因此不需要做任何处理(手动内存管理需要执行release让引用计数减1 )
ARC中也不能手动调用dealloc方法(包括@selecter(dealloc)等隐式调用),手动内存管理中是不能显示调用dealloc方法,除非是父类的dealloc
ARC有效时不允许调用父类的dealloc,尽管可以创建一个定制的dealloc方法来释放资源而不是实例变量(实例变量系统会自动释放),
但也不要调用[super dealloc],否则会出现编译错误,因为编译器会自动去处理这些事情
启用ARC编译代码时,不能使用gcc,而要使用clang,同时编译选项中需加上-fobjc-arc,而使用-fno-objc-are明确告诉编译器不想使用ARC
基本注意事项:P94
反向指针,只通过指针指向,不拥有所有权的变量,和拥有所有权的实例变量在内存方面的处理截然不同,处理不当就会造成内存泄漏
弱引用:
ARC中为了解决循环引用,引入的类型,能够引用对象,但不会成为对象的所有者,不影响对象本身的回收
通过存储一个指向对象的指针创建,且不保存对象,OC 中使用_ _weak修饰符定义
弱引用情况下,对变量赋值还是解除引用变量的引用计数都不会发生变化,强弱引用都会被隐式初始化为nil
弱引用会在其指向的实例对象被释放后自动变成nil,使弱引用不会变成野指针(弱引用的自动nil化功能)
生命周期修饰符:(所有权修饰符)
用于修饰指针类型变量的修饰符
共4种:
strong、__weak、autoreleasing、__unsafe_unretained
对象之间引用关系的基本原则:
使用ARC时应该尽量保证对象之间的关系呈树形结构,这样,当一个对象被释放的时候,这个对象引用的对象也会被自然的释放掉
在使用反向指针指向父节点,或者两个对象之间相互引用,进行跨越子树间的引用等时,容易产生循环引用,此时可以使用弱引用,或通过手动给一方赋值nil,打破循环引用
__unsafe_unretained
未初始化的情况下,其变量的初始值不定,释放后变量的指向也是不定的,ARC中不会管理这种类型的变量,所以它不安全在有可能变成野指针
使用__unsafe_unretained所修饰的变量称为 非nil化的弱指针,它不会保持赋值的对象,也不会在赋值对象在释放后被自动设置为nil,所以当它所指向的内存区域被释放了,这就是一个野指针了
将生成的对象直接赋值给__unsafe_unretained类型对象时,也会导致新生成的对象被直接释放掉
在手动管理内存是有可能在赋值时没对变量进行retain操作,这就相当于在ARC 中用_weak,__unsafe_unretained修饰了变量的行为,这种代码迁移到ARC环境一定要小心其所有权问题
在使用ARC的程序中,需要使用__bridge修饰符来实现id 类型与 void* 类型的相互转换,ARC可以管理OC 对象,而Core Fundation类型对象不在ARC管理范畴内,
而IOS中 主要由这两种对象组成,所以当转换这两种类型时(有/没有 ARC管理),需要告诉编译器怎样处理对象的所有权(更太多详情参考《Objective-c编程全解》附录B)
在ARC有效的情况下,使用__unsafe_unretained修饰的变量时,以及在手动内存管理模式下使用可能被编译的模块时,setter方法无法仅从接口的定义判断是否应该对传入的参数进行
保持操作,而如果没有进行保存操作,就有可能出现野指针。此时有一种减少野指针的方法是,当不再使用传入对象时,将其值赋值为nil,典型做法是在dealloc方法中进行如下处理:
[someone setFrind:nui];
[controller setDelegate:nil];《Objective-c编程全解》P102
写回传:
相当于C中的按引用传递
当一个函数或方法有多个返回值时,可以通过函数或方法的参数传入一个指针,将返回值写入指针所指向的空间(???形参可以吗???)
常用于当一个方法在处理过程中出现错误时,通过指向NSError的二重指针返回错误的原因和种类
只可以把nil或临时变量的指针用于写回传,不可以把静态变量的指针、数组首地址的指针或内部变量的指针用于写回传
将二重指针用于方法的参数时,可以给二重指针加上out修饰符,使用写回传时方法调用和方法返回都会发生值传递,而使用out修饰符时就可以使函数只在返回的时候发生值传递,
从而省略调用函数时的值传递。(how???)(out原本用于提高调用分布式对象的效率)
__autoreleasing
为了获得一个延迟释放的对象
例如:传递一个未初始化的对象的引用(二重指针的形式)到一个方法中,并在此方法中实例化此对象,并希望返回时这个对象自动加入到自动释放池中
ARC有效的程序中可以使用C语言数组保存OC 的对象
ARC有效的程序中不可以在C语言的结构体(或共用体)中定义OC 对象,因为编译器不能自动释放他们内部的OC对象,常用的解决方法是使用OC 中的类带替结构体或共用体,
若因为效率或其他原因必须使用,可以使用__unsafe_unretained修饰符来修饰结构体中的OC 变量,此时,编译器不会管理此变量的内存,需要完全手动管理内存(引用计数也不可用)
我们经常用准备好的结构体数组来初始化程序,如果数组仅仅是为了初始化用而不需要修改数组中的内容的话,可以给结构体中的对象加上const__unsafe__unretained修饰符,
来回避内存管理方面的各种问题
如果要将未使用arc的命名规则有问题的程序迁移到arc环境中,因为某些原因没法修改这些方法的名字,此时可通过给方法加上事先定义好的一些宏来告诉编译器应该
如何对这个方法的返回值进行内存管理。宏的声明需要放置到方法末尾。
编译时这些宏会被替换为注释。这不属于语言的一部分是编译器特有的拓展功能。可使用条件编译来区分ARC是否有效。
例:NS_RETURNS_RETAINED 指明这个方法和init、copy开头的方法一样由调用端负责释放返回的对象。
NS_RETURNS_NOT_RETAINED 指明这个方法不属于内存管理方面的方法,调用端无需释放返回的对象
这些宏都被定义在NSObjCRuntime.h中