zoukankan      html  css  js  c++  java
  • OC基础(26)

    集合对象的内存管理

    本小节知识点:

    1. 【掌握】集合对象的内存管理
    2. 【理解】集合对象内存管理总结

    1.集合对象的内存管理

    • 当一个对象加入到集合中,那么该对象的引用计数会+1
    • 当集合被销毁的时候,集合会向集合中的元素发送release消息
        NSMutableArray *arr = [[NSMutableArray alloc] init];
    
        Person *p = [[Person alloc] init];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [arr addObject:p];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [p release];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [arr release];
    • 当一个对象加入到集合中,那么该对象的引用计数会+1
    • 当把一个对象从集合中移除时,会向移除的元素发送release消息
        NSMutableArray *arr = [[NSMutableArray alloc] init];
        Person *p = [[Person alloc] init];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [arr addObject:p];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [arr removeObject:p];
        NSLog(@"retainCount = %lu", [p retainCount]);
        [p release];
        [arr release];

    2.集合对象内存管理总结

    • 1.官方内存管理原则

      • 1> 当调用alloc、new、copy(mutableCopy)方法产生一个新对象的时候,就必须在最后调用一次release或者autorelease
      • 2> 当调用retain方法让对象的计数器+1,就必须在最后调用一次release或者autorelease
    • 2.集合的内存管理细节

      • 1> 当把一个对象添加到集合中时,这个对象会做了一次retain操作,计数器会+1
      • 2> 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1
      • 3> 当一个对象从集合中移除时,这个对象会一次release操作,计数器会-1
    • 3.普遍规律

      • 1> 如果方法名是addinsert开头,那么被添加的对象,计数器会+1
      • 2> 如果方法名是removedelete开头,那么被移除的对象,计数器-1

    Copy

    本小节知识点:

    1. 【理解】copy基本概念
    2. 【理解】Copy的使用
    3. 【理解】copy快速入门

    1.copy基本概念

    • 什么是copy

      • Copy的字面意思是“复制”、“拷贝”,是一个产生副本的过程
    • 常见的复制有:文件复制

      • 作用:利用一个源文件产生一个副本文件
    • 特点:

      • 修改源文件的内容,不会影响副本文件
      • 修改副本文件的内容,不会影响源文件
    • OC中的copy

      • 作用:利用一个源对象产生一个副本对象
    • 特点:

      • 修改源对象的属性和行为,不会影响副本对象
      • 修改副本对象的属性和行为,不会影响源对象

    2.Copy的使用

    • 如何使用copy功能

      • 一个对象可以调用copy或mutableCopy方法来创建一个副本对象
      • copy : 创建的是不可变副本(如NSString、NSArray、NSDictionary)
      • mutableCopy :创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
    • 使用copy功能的前提

      • copy : 需要遵守NSCopying协议,实现copyWithZone:方法
    @protocol NSCopying
    - (id)copyWithZone:(NSZone *)zone;
    @end
    • 使用mutableCopy的前提
      • 需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
    @protocol NSMutableCopying
    - (id)mutableCopyWithZone:(NSZone *)zone;
    @end

    2.深复制和浅复制

    • 浅复制(浅拷贝,指针拷贝,shallow copy)
      • 源对象和副本对象是同一个对象
      • 源对象(副本对象)引用计数器+1,相当于做一次retain操作
      • 本质是:没有产生新的对象
        NSString *srcStr = @"lnj";
        NSString *copyStr = [srcStr copy];
        NSLog(@"src = %p, copy = %p", srcStr, copyStr);
    • 深复制(深拷贝,内容拷贝,deep copy)
      • 源对象和副本对象是不同的两个对象
      • 源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
      • 本质是:产生了新的对象
        NSString *srcStr = @"lnj";
        NSMutableString *copyStr = [srcStr mutableCopy];
        NSLog(@"src = %p, copy = %p", srcStr, copyStr);
        NSLog(@"src = %@, copy = %@", srcStr, copyStr);
        [copyStr appendString:@" cool"];
        NSLog(@"src = %@, copy = %@", srcStr, copyStr);
        NSMutableString *srcStr = [NSMutableString stringWithFormat:@"lnj"];
        NSString *copyStr = [srcStr copy];
        [srcStr appendString:@" cool"];
        NSLog(@"src = %p, copy = %p", srcStr, copyStr);
        NSLog(@"src = %@, copy = %@", srcStr, copyStr);
        NSMutableString *srcStr = [NSMutableString stringWithFormat:@"lnj"];
        NSMutableString *copyStr = [srcStr mutableCopy];
        [srcStr appendString:@" cool"];
        [copyStr appendString:@" 520it"];
        NSLog(@"src = %p, copy = %p", srcStr, copyStr);
        NSLog(@"src = %@, copy = %@", srcStr, copyStr);
    • 只有源对象和副本对象都不可变时,才是浅复制,其它都是深复制

    copy与内存管理

    本小节知识点:

    1. 【理解】copy与内存管理

    1.copy与内存管理

    • 浅拷贝

      • 原对象引用计数器+1
      • 必须对原对象进行释放 objc char *cstr = "this is a c string"; NSString *str1 = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"str = %lu", [str1 retainCount]); NSString *str2 = [str1 copy]; NSLog(@"str = %lu", [str1 retainCount]); [str2 release];必须做一次release
    • 深拷贝

      • 必须释放新对象 objc char *cstr = "this is a c string"; NSString *str1 = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"str = %lu", [str1 retainCount]); NSMutableString *str2 = [str1 mutableCopy]; NSLog(@"str = %lu", [str1 retainCount]); [str2 release]; // 必须做一次release

    提示可以创建iOS项目演示

    @property中的copy关键字

    本小节知识点:

    1. 【理解】@property中的copy的作用
    2. 【理解】@property内存管理策略选择

    1.@property中的copy的作用

    • 防止外界修改内部的值
        @interface Person : NSObject
        @property (nonatomic, retain) NSString *name;
        @end
        NSMutableString *str = [NSMutableString stringWithFormat:@"lnj"];
    
        Person *p = [[Person alloc] init];
        p.name = str;
        // person中的属性会被修改
        [str appendString:@" cool"];
        NSLog(@"name = %@", p.name);
    • 防止访问对象对象已经释放
      • 不用copy情况 objc Person *p = [[Person alloc] init]; p.name = @"lnj"; Dog *d = [[Dog alloc] init]; d.age = 10; NSLog(@"retainCount = %lu", [d retainCount]); // 1 p.pBlock = ^{ // 报错, 调用之前就销毁了 NSLog(@"age = %d", d.age); }; [d release]; // 0 p.pBlock(); [p release];
      • 用copy情况
        Person *p = [[Person alloc] init];
        p.name = @"lnj";
        Dog *d = [[Dog alloc] init];
        d.age = 10;
        NSLog(@"retainCount = %lu", [d retainCount]); // 1
        p.pBlock = ^{
            // 会对使用到的外界对象进行一次retain
            NSLog(@"age = %d", d.age);
            NSLog(@"retainCount = %lu", [d retainCount]); // 1
        };
        [d release]; // 1
        p.pBlock();
        [p release];

    2.@property内存管理策略选择

    • 非ARC

      • 1> copy : 只用于NSStringlock
      • 2> retain : 除NSStringlock以外的OC对象
      • 3> assign :基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign
    • ARC

      • 1> copy : 只用于NSStringlock
      • 2> strong : 除NSStringlock以外的OC对象
      • 3> weak : 当2个对象相互引用,一端用strong,一端用weak
      • 4> assgin : 基本数据类型、枚举、结构体(非OC对象)

    自定义的类实现copy操作

    本小节知识点:

    1. 【理解】自定义类实现copy操作

    1.自定义类实现copy操作

    • 让类遵守NSCopying协议
    • 实现 copyWithZone:方法,在该方法中返回一个对象的副本即可。
    • 在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致, 并返回该对象.

      zone: 表示空间,分配对象是需要内存空间的,如果指定了zone,就可以指定 新建对象对应的内存空间。但是:zone是一个非常古老的技术,为了避免在堆中出现内存碎片而使用的。在今天的开发中,zone几乎可以忽略

    • 无父类实现

    -(id)copyWithZone(NSZone *)zone{
    
       CustomMode *custom = [[[self class]  copyWithZone:zone]  init];
    
       Custom ->_a = [_a copyWithZone:zone];
    
       Custom -> _c = _c;//不是对象的 直接赋值
    
       Return custom;
    
    }
    • 有父类实现

      • 不调用父类方法, 无法拷贝父类中继承的属性
      • 不重新父类copyWithZone, 无法拷贝本来中的特有属性 ```objc -(id)copyWithZone(NSZone *)zone{

      CustomModel *custom = [super copyWithZone:zone]; …. Return custom; }

  • 相关阅读:
    类图的基本知识
    设计模式——单例模式
    解决phpcms V9 推荐位无法排序
    PHPCMS 多站点管理切换问题
    天天团购系统-简单的目录结构
    php的时间输出格式
    天天团购--源码目录结构
    天天团购系统--部分模板语法
    PHP json数据格式化方法
    PHP json_encode中文乱码解决方法
  • 原文地址:https://www.cnblogs.com/zhoudaquan/p/5017853.html
Copyright © 2011-2022 走看看