iOS内存优化

作者: Mark_大东 | 来源:发表于2020-03-02 21:39 被阅读0次

    无论面试还是工作希望这篇文章可以解决所有关于iOS内存优化的问题。

    所有问题的解决方式都是有基本上的三个提问:是什么?为什么?怎么做?因此对于内存优化的点首先可以做出如下提问:为什么需要内存优化?内存消耗在什么地方?系统是否提供内存管理的方法?处理内存管理的最佳实践有哪些?以上问题在下面的文档中都会提现并作出解答。

    为什么内存需要优化?

    应用的内存使用量超过单个进程的上线,就会被操作系统终止。

    内存的消耗体现在什地方?

    内存消耗指的是应用消耗的RAM。应用中内存消耗分为两部分:栈大小、堆大小。每个进程的所有线程共享一个堆空间,每个线程都有专用的栈空间。

    堆大小

    系统分配给应用的堆大小不会超过512M,同时应用不能控制分配给它的堆,只有操作系统可以管理堆。通过类创建的对象相关的所有数据都存放在堆中。

    消耗堆内存的操作:使用NSSting、载入图片、创建使用Json/XML数据等。(待补充)

    优化点:图片缓存、数据缓存、降低接口数据大批量输出等。(待补充)

    栈大小

    栈大小跟线程有关,那么创建线程通常是用来做什么呢?

    常见的创建线程有:异步请求、本地缓存sql数据等。更具栈大小的优化点可知不能无限先在创建的线程调用方法。

    降低栈大小的操作:相爱时可被递归调用的最大方法树、一个方法最多可以使用的变量数、视图层级在可嵌入的最大深度。

    内存的管理模型是什么?

    或者说iOS是如何管理内存的?

    内存管理模型基于持有关系的概念。如果一个对象正处于被持有关系状态,那它占用的内存就不会被回收。这种持有关系技术通常被称为引用计数。MRC:手动引用计数、ARC:自动引用计数。同时因为ARC的带来的新的引用特性:弱引用。

    弱引用:不会增加引用计数,因此不会扩展对象的引用声明周期。

    强引用:强引用是默认的引用类型,被强引用指向的内存不会释放,强引用会增加引用计数,同时会扩展对象的声明周期。

    自动引用计数:

    特点:不在使用retain、release和autorelease;ARC是编译器的一种特性,它会评估对象在代码中,并在编译时自动注入适合的内存管理调用。同时系统默认开始ARC。

    变量限定符:

    __strong、 _weak 、_unsafe_unretained、 _autoreleasing

    Person * _strong p1 = [[Person allon]init];
    //创建对象后引用计数为1,并且对象在p1引用期间不会被回收
    Person * _weak p2= [[Person allon]init];
    //创建对象后引用计数为0,对象会被立即释放,且p2将被置为nil
    Person * _unsafe_unretained p3 = [[Person allon]init];
    //创建对象后引用计数为0,对象会被立即释放,且p3不会被置为nil
    Person * _autoreleasing  p4= [[Person allon]init];
    //创建对象后引用计数为1,当方法返回时对象会被立即释放
    
    属性限定符:

    strong 、weak 、assign 、copy 、retain 、unsafe_unretained

    注意点:布尔类型使用assign限定符、retain是MRC时期的产物

    循环引用:

    当两个不同的对象各有一个强引用指向对方,就会造成循环引用

    循环引用的常见场景:

    委托、Blocks、线程与计时器、键值对

    处理方式如下:

    委托
    @protocol TestDataDelegate <NSObject>
    - (void)onDataModel;
    @end
    
    @interface TestClass
    @property (nonatomic,weak) id<TestDataDelegate>delegate;
    - (void)delegate;
    @end
    
    @implementation TestClass
    - (void)cancel{
      self.delegate = nil
    }
    @end
    
    Blocks
    SomeViewController  *vc = [[SomeViewController alloc]init];
    _weak typeof(weakSelf) = self;
    [self presentViewController:vc animated:YES completion:^{
        typeof(self) theSelf = weakSelf;
        if (theSelf !=nil){
            theSelf.data = vc.data;
            [theSelf dismissViewControllerAnimated:YES completion:nil];
        } 
    }];
    
    线程与计时器
    - (void)close{
        [self.timer invalidate];
        self.timer = nil;
    }
    
    观察者:
    - (void)dealloc{
        [self removeObserver];
    }
    

    内存分析工具:

    使用Instruments选择Leaks进行检测。

    内存管理的最佳实践?

    • 避免大量的单例
    • 对子对象使用 _strong
    • 对父对象使用_weak
    • 对是引用图闭合的对象如委托代理使用_weak
    • 对数值属性NSInteger SEL CGFloat等使用assign
    • 对块属性,使用copy
    • 避免在块内直接引用外部的变量。在块外面将他们weakify,并在块内再讲他们strongify.
    • 进行必要的清理:销毁定时器、移除观察者、解除回调

    备注:关于iOS内存优化先关知识的整理,相关内容来时《高性能iOS开发》、网络资源。以上内容如果需要会在后续慢慢补充完善,知道彻底理解内存相关的知识点。

    相关文章

      网友评论

        本文标题:iOS内存优化

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