OC加强DAY02 - ARC与分类

来源:互联网 发布:淘宝怎么增加权重 编辑:程序博客网 时间:2024/05/17 02:58

        • class关键字
        • 两个对象相互引入的内存泄露 循环retain
        • 自动释放池的使用
          • 快速创建对象补充
        • ARC 自动引用计数
          • MRC下通过引用计数器判断 ARC下通过强若指针判断
        • ARC下回收的准则
        • ARC机制下多个对象的内存管理
        • property参数总结
        • MRC和ARC的兼容
        • MRC转换ARC
  • 分类
          • 分类的总结

@class关键字

  • 问题:当两个头文件相互#import,就会造成死循环,所以不能相互
    1. 其中一个头文件中不要用#import,而是用@class HMPerson;,告诉编译器这是一个类.
    2. 在.m文件中,如果要用到HMPerson类中的方法,就再#import "HMPerson.h"来引入.
    3. 对比#import@class;
  1. #import是一个预处理指令,将文件内容拷贝到写指令的地方
  2. @class不是一个预处理指令,只是高速编译器是一个类,不要报错.

两个对象相互引入的内存泄露 循环retain

  1. 当两个对象相互引用的时候 A对象的属性,指向B对象. B对象的属性指向A对象.
  2. 这个时候如果两边都是用retain,就会出现内存泄露.都回收不了.

    • 解决方法:
  3. 一端使用assign 一端使用retain
  4. 使用assign dealloc中不需要再去release这个对象了.

==那使用assign的一段被调用会不会有问题?为什么不调用的时候跟一个release?==

自动释放池的使用

  • 自动释放池的原理:是用来存储对象的
  1. 存入到自动释放池的对象,在自动释放池被销毁的时候,会自动调用这个对象的release方法.
  2. 将创建的对象存入自动释放吃,就不需要手动匹配release了.

“`objc
@autoreleasepool{
//大括号内就是自动释放池
HMPerson *p1 = [[[HMPerson alloc] init] autorelease];
}//这个池子的大括弧执行完毕,这个池子就销毁了.

  • 七大注意
    1. 怎么放进去? 只有在释放池中调用了autorelease方法,才会存进去.

如果只是将对象的创建代码写在释放池中,而没有调用autorelease方法是不会自动释放的

  1. 可以在外面创建对象,但必须在释放池里面调用一次autorelease方法.

将一个对象存储到自动释放池中最重要的的一步就是这一步

  1. 自动释放池结束后不是销毁对象,而是发送一条release消息.会不会销毁看引用计数器
  2. 如果在释放池中调用多次autorelease方法. 调用几次,结束时就发送几条消息.这会出现僵尸对象错误
  3. 如果pool中调用了autorelease 还匹配了一个 release 就会造成野指针错误操作僵尸对象..
  4. 将对象存储到pool中不会让引用计数器+1,所以
  5. 自动释放池可以嵌套. pool里面还可以有pool.哪里调用autorelease方法,就存到当前那个池里面.
  1. 不要将大内存对象放到延迟释放池中
  2. 不要将循环操作放进去造成内存峰值上升.
快速创建对象补充
  1. 类方法创建对象要求返回的对象已经被autorelease过了.(MRC)
  2. init方法不用.
  3. 这样在自动释放池中调用类方法创建对象会自动autorelease
  4. initWith方法中,可以调用[seper initWith]方法,少写代码
  5. initWith方法中OC对象的赋值要用.语法,调用set方法,进行retain操作.

ARC 自动引用计数

  1. 什么是ARC
  1. WWDC2011 和 IOS5引入的最激动人心的变化. 是LLVM3.0编译器的一项特性.
  2. 开启ARC时永远不要写retain,release,autorelease. 永远不要调用dealloc这三个关键字
  3. 特别注意,==编译器是编译机制,在编译代码的时候==,加入这几个关键字.
  1. ARC机制下,对象何时被释放.
  1. 本质: 对象的引用计数器为0的时候自动释放.
  2. ARC: 开发者不用写,编译器在编译代码的时候,自动在合适的地方插入这些代码
  3. 表象: ==只要没有强指针指向这个对象,这个对象就会被立即回收==.(ARC机制下)
  1. 强指针与若指针
  1. 默认的都是强指针
  2. 也可以用__strong HMPerson *p1 = [HMPerson new]来显示的声明这是一个强指针
  3. 弱指针: 使用__weak HMPerson *p2 = p1;标识的就是若指针
  4. 都是指针,用类存储地址,都可以访问这个对象成员.
  5. 唯一的区别就是ARC下对象是否回收的标准.
    __strong HMPerson *p1 = [HMPerson new];__weak HMPerson *p2 = [HMPerson new];p1 = nil; //这句话执行完以后,还有p2指向他,但是没有任何强指针指向他,则立即回收了.
MRC下通过引用计数器判断, ARC下通过强若指针判断.

ARC下回收的准则

  1. 指向对象所有的指针都被回收的时候.
  2. 创建对象的时候用一个若指针存储创建的对象,出来就死了.
  3. 对象没有任何强指针指向会被回收,以前指向他的若指针自动设置为nil,保证不出现野指针.
  4. 4.

ARC机制下多个对象的内存管理

  1. 我们在MRC模式下用的@property参数,ARC下不要用retain参数.
  2. 在ARC下,我们只要考虑@property==生成的私有属性是强类型还是弱类型的.==
  3. @property参数 还有strongweak.

    • ARC下 OC对象用strong,非OC对象用assign
  4. strong替换了retain
  5. assign还是给C语言对象
  1. 在ARC机制下,如果出现了循环引用.

    A对象中有1个属性是B对象. B对象中有1个属性是A对象.

    如果两边都用strong.就会发生内存泄露.

    你掐着我,我掐着你,即使是没有人指向的对象,他们也没有销毁

  1. 解决方案:

1端使用strong 另外1端使用weak

@property参数总结

  1. 与多线程相关的参数.
  1. atomic , nonatomic
  2. 这两个参数,无论在MRC还是ARC下都可以使用. 使用nonatomic
  1. retain: 只能使用在MRC模式下.
  • 在MRC模式下: 当属性的类型是OC对象的时候,绝大多数场景之下使用retain.
  • assign: 可以使用在ARC和MRC模式之下.
    1. 在ARC下: 当属性的类型是非OC对象的时候,一律使用assign.
    2. 在MRC模式下: 当属性的类型是非OC对象的时候,一律使用assign.
    3. 在MRC模式下.出现循环引用的时候. 1边使用assign 1边使用retain.
  1. strong: 只能使用在ARC模式下.当属性的类型是OC对象的时候,绝大多数场景之下使用strong.

weak:只能使用在ARC模式下 当出现循环引用的时候.1边使用strong 1边使用weak.

  1. getter setter 修改方法名字.

无论是ARC还是MRC都可以通过他们修改方法的名字.

  1. readonly readwrite.

ARC,MRC都可以,管理生成set,get方法.

MRC和ARC的兼容

  • 你在使用ARC开发,别人是MRC.你要引入几个类使用MRC,其他的还是用ARC

build phases 下 compole sources (x items) 下 在文件后面写 -fno-objc-arc

MRC转换ARC

edit -> convert -> to object-c ARC

千万别这么用,有很大的可能会出问题.转换很粗暴,就是替换.

正式的项目不要轻易去转,不能逆转,记得备份几份.

分类

  1. 分类

类别 类目, category

  1. 我们要写个学生类,这个类就会有很多的属性方法.
  1. 本来应该将全部方法写在学生类中去,但是很==拥挤.太多了.后期不好维护管理==
  2. 可以根据方法的功能不同,将这些方法进行分组
  1. 怎么分类

1.把功能相似的方法放在同一个模块中,这样方便我们后期的维护和管理
2. 如何为类添加一个分类 NewFile–>OC File –> category

这个时候产生了一个模块,

.h声明文件
.m实现文件
3. 分类的声明和实现
分类的声明

//为一个已经存在的类添加一个分类名(itheima)@interface HMStudent (itheima)@end//分类的实现.@interface 本类名 (分类名)@end
  1. 如何理解分类?就是本类的一部分.分在了多个模块中
  1. 分类的使用
如果要使用分类中的成员,就必须要引入分类的头文件..
  1. 使用分类的注意.
  1. 分类的作用: 将1个类分为多个模块. 将相似功能的方法写在同1个模块中,方便我们后面代码的维护.
  2. 分类中只能增加方法.不能增加属性.
  3. 分类中可以写@property. 分类中的@property只会生成getter setter的声明.不会生成私有属性和getter setter的实现.实现要自己去实现.也不能用==@sythesize==
  4. 本类中的真私有属性,是无法在分类中访问. 但是可以使用对应的getter setter方法来访问.但是声明在@interface中的属性可以在分类中访问.
  5. 分类中可以存在和本类同名的方法.这个时候,调用这个方法的时候,不管有没有引入分类.调用的都是分类的这个方法.如果多个分类中有同名的方法,优先调用最后编译的分类中的方法.
分类的总结
  1. 分类是来干嘛的?

将1个类分为多个模块的.在不改变原有类的基础上为分类扩充方法

  1. 什么时候需要使用分类将类分为多个模块.
  1. 团队开发,多个人合作写1个类的时候.
  2. 当1个类过于臃肿的时候,我们就可以考虑使用分类将这个类分为多个模块.将功能相似的方法写在同1个模块中,方便后期代码的维护.
  1. 分类的唯一的好处: 将1个复杂的类分为多个模块,方便我们以后代码的维护.
0 0
原创粉丝点击