美文网首页
_01_《高性能iOS应用开发》——内存管理

_01_《高性能iOS应用开发》——内存管理

作者: 饮长刀 | 来源:发表于2017-06-27 23:23 被阅读24次
    • 应用中新创建的每个线程都有专用的栈空间,线程的最大栈空间很小,如果层级太深,可能造成栈溢出。
    • 每个进程的所有线程共享同一个堆。
    • 在相册类 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 块的情况:

      1. 当有一个创建了很多临时对象的循环时,在循环中使用 autoreleasepool 可以为每一次循环释放内存。循环次数多时,对内存的需求大大降低。
      2. 自己创建的线程也应创建一个自己的 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 设置为任务类的代理。

    • 观察者
      键值观察和通知中心不会维持观察对象、被观察对象以及上下文对象的强引用。如果要持续对一个对象进行观察,需要自行维护对它的强引用。

    • 避免大量使用单例和全局状态对象。

    相关文章

      网友评论

          本文标题:_01_《高性能iOS应用开发》——内存管理

          本文链接:https://www.haomeiwen.com/subject/ttsycxtx.html