IOS 内存分析 Xcode

主要目的就是为了检测程序是否存在内存泄露

  • MRC target -> build setting -> 搜索 automatic reference counting
    截屏2020-06-01下午4.32.53.png

1. 静态内存分析(Analyze)

  • 概念:

静态内存分析是不运行程序,直接对代码进行分析.
根据代码的上下文的语法结构,来分析内存状况

  • 作用:
    调整环境到MRC

逻辑错误:访问未初始化的变量或者野指针等;
声明错误:从未使用过的对象;
内存管理错误:如内存泄漏等;(MRC&ARC)

  • 缺点:

不一定准确,但是如果发现有提示,那么去结合上下文看一下,这里的代码是否有问题

  • 场景演练(OC):

    MRC 下桥接
    Foundation 到 CoreFoundation框架的数据类型转换
    强制数据类型转换, 不会移交对象内存管理所有权
    CoreFoundation 到 Foundation框架的数据类型转换
    强制数据类型转换, 不会移交对象内存管理所有权


MRC下的静态分析

//    > 逻辑错误:访问未初始化的变量或
        NSObject *obj;
        NSLog(@"%@", obj);
未初始化
// 野指针等;
    NSObject *obj = [[NSObject alloc] init];
    [obj release];
    NSLog(@"%@",obj);
野指针
// > 声明错误:从未使用过的对象;
     NSObject *obj = [[[NSObject alloc] init] autorelease];
从未使用过
// 测试不准确的地方
    NSObject *obj = [self lost];
    NSLog(@"%@", obj);
    [obj release];
    
}

- (NSObject *)lost
{
    return [[NSObject alloc]init];
}
不准确

使用Corefoundation的框架内容要记得释放

mrc使用corefoundation

MRC下的桥接

- (void)mrc
{
    //MRC下桥接
    //Foundation 到 CoreFoundation框架的数据类型转换
    NSString *str = [[NSString alloc] init];
     // CFStringRef , 这种转换, 属于直接转换, 不会移交对象的内存管理权
    CFStringRef strRef = (CFStringRef)str;
    NSLog(@"%@", strRef);
    [str release];
    
    //CoreFoundation 往 Foundation框架的数据类型转换
     CFStringRef strRef2 = CFStringCreateWithCString(CFAllocatorGetDefault(), "123", kCFStringEncodingUTF8);
     // 这种转换, 属于直接转换, 不会移交对象的内存管理权
    NSString *str2 = (NSString *)strRef2;
    CFRelease(strRef2);
    
}

ARC下的桥接

//Foundation 到 CoreFoundation框架的数据类型转换
    NSString *str = [[NSString alloc] init];
     // (__bridge CFStringRef)  等同于 MRC下面的直接转换, 不会移交对象的内存管理权
    CFStringRef strRef = (__bridge CFStringRef)(str);
    
    NSLog(@"%@", strRef);
    
    // CFBridgingRetain == __bridge_retained CFStringRef
       // 这种方式转换, 会移交对象的内存管理权
    CFStringRef strRef2 = (__bridge_retained CFStringRef)(str);
    NSLog(@"%@", strRef2);
    CFRelease(strRef2);
    
    //CoreFoundation 到 Foundation框架的数据类型转换
    CFStringRef strRef3 = CFStringCreateWithCString(CFAllocatorGetDefault(), "123", kCFStringEncodingUTF8);
    // __bridge NSString * 等同于 MRC下面的直接转换, 不会移交对象的内存管理权, 还是释放原来的对象
//    NSString *str3 = (__bridge NSString*)(strRef3);
//    NSLog(@"%@", str3);
//    CFRelease(strRef3);
    // CFBridgingRelease == __bridge_transfer NSString *
    // 这种方式转换, 会移交对象的内存管理权
    NSString *str4 = (__bridge_transfer NSString *)(strRef3);
    NSLog(@"%@", str4);

关于Swift中使用CoreFoundation 数据类型

使用了"类型重映射"机制, 转换成为了能够自动管理内存的对象, 不需要我们手动释放


内存分配

作用

查看是内存的分配情况
查看内存是否有释放

  • UIImage 的两种创建方法测试
  • 加载UIImage的不同方式
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
         // 通过 named 创建的图片资源, 不会被释放, 在内存中, 只有一份
        //let imageNew = UIImage(named: "liudog.png")
        
        let  path = Bundle.main.path(forResource: "liudog.jpg", ofType: nil)
//图片没有缓存,可以被释放,
        let imageNew = UIImage(contentsOfFile: path!)
        
        if imageView == nil
        {
            return
        }
        imageView.image = imageNew
        
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
    {
        if imageView == nil
        {
            return
        }
        imageView.removeFromSuperview()
    }

概念解释

Anonymous VM(匿名虚拟内存)是系统为程序预留的、可能会立即被重复使用的一部分可用内存

图片使用技巧

图片在沙盒中的存在形式

1.如果项目的Deployment Target <= 6.x (不支持图片压缩), 所有图片直接暴露在沙盒的资源包(main Bundle), 不会压缩到Assets.car文件

  1. 如果项目的Deployment Target >= 7.x (支持图片压缩)

1 放在Images.xcassets里面的所有图片会压缩到Assets.car文件, 不会直接暴露在沙盒的资源包(main Bundle)
2 没有放在Images.xcassets里面的所有图片会直接暴露在沙盒的资源包(main Bundle), 不会压缩到Assets.car文件

  1. 使用对比
  • 会压缩到Assets.car文件, 没有直接暴露在沙盒的资源包(main Bundle)条件 : "Deployment Target >= 7.x" 并且是 "放在Images.xcassets里面的所有图片"影响 : 无法得到图片的全路径, 只能通过图片名(imageNamed:方法)来加载图片, 永远会有缓存
  • 不会压缩到Assets.car文件, 直接暴露在沙盒的资源包(main Bundle)
    ** 条件 :** 除1> 以外的所有情况
    ** 影响 :** 可以得到图片的全路径, 可以通过全路径(imageWithContentsOfFile:方法)来加载图片, 不会有缓存
  1. 结论
  • 小图片\使用频率比较高的图片,放在Images.xcassets里面
  • 大图片\使用频率比较低的图片(一次性的图片, 比如版本新特性的图片)

动态内存分析

  • 作用 :检测程序在运行过程中是否存在内存泄露
  • 演练:> 模拟循环引用, 测试内存泄露

    Leaks

4. 内存使用总结

如何让程序尽量减少内存泄漏

  • 1.非ARC
  • Foundation对象(OC对象) : 只要方法中包含了alloc\new\copy\mutableCopy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次release或者1次autorelease
  • CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
  • 2.ARC
  • 只自动管理OC对象, 不会自动管理C语言对象
  • CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
  • 如果是swift里面, 使用* CoreFoundation对象(C对象) , 不需要手动释放. 因为使用了"类型重映射"机制, 可以把对象转换成为自动管理内存的对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值