- 应用中新创建的每个线程都有专用的栈空间,线程的最大栈空间很小,如果层级太深,可能造成栈溢出。
- 每个进程的所有线程共享同一个堆。
- 在相册类 APP 中,如果所有的图片都在 dataSource 中,这个数组将会很大,从而导致很高的峰值内存使用。可以固定数组的大小,在用户滚动视图时换入或者换出图片。
- A方法创建了一个对象并返回了a,B方法调用A方法,B内引用a,那么不应该在 B 中释放 a,因为 B 方法中没有创建实体对象,不要在 B 中使用 release. 当创建一个对象并将其从非 alloc 方法返回时,应使用 autorelease。这样可以保证对象被释放。
- (NSString *)address {
NSString *ad = [[[NSString alloc] initWithString:@"贝克街 221B"] autorelease];
return ad;
}
...
- (void)showPersonAddress:(Person *)p {
NSString *address = [p address];
NSLog(@"Person's Address: %@", address);
}
-
自己创建 autoreleasepool 块的情况:
- 当有一个创建了很多临时对象的循环时,在循环中使用 autoreleasepool 可以为每一次循环释放内存。循环次数多时,对内存的需求大大降低。
- 自己创建的线程也应创建一个自己的 autoreleasepool.
-
__weak
: 当没有强引用指向对象时,弱引用会被置为 nil. -
__unsafe__unretained
: 当没有强引用指向对象时,弱引用不会被置为 nil. -
循环引用
双向链表和环形链表中也存在循环引用。此时,一旦明确对象不会再被使用,需要编写代码打破链表的链接。 -
线程与计时器
- (void)startCountdown {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateFeed:) userInfo:nil repeats:YES];
}
- (void)dealloc {
[self.timer invalidate];
}
很明显上面的例子中产生了循环引用,直到 [self.timer invalidate] 执行,timer 才会取消对 self 的强引用,但是由于建立了循环引用,这里的 dealloc 并不会调用,timer 并不会执行 invalidate。所以需要自定义一个清理的方法执行清理操作。这样的清理方法可以在离开当前页面点击返回时调用。
另一种清理方案是将持有关系分散到多个类中——任务类执行具体动作,所有者类调用任务。类似于将 taget 设置为任务类的代理。
-
观察者
键值观察和通知中心不会维持观察对象、被观察对象以及上下文对象的强引用。如果要持续对一个对象进行观察,需要自行维护对它的强引用。 -
避免大量使用单例和全局状态对象。
网友评论