OC语言-内存管理
OC语言-内存管理
盘盘的灰灰 发表于2年前
OC语言-内存管理
  • 发表于 2年前
  • 阅读 6
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】买域名送云解析+SSL证书+建站!>>>   

  • 万能指针(NSObject、id). instancetype

         NSObject和id 它们都是万能指针,可以指向任意的OC对象.

         NSObject指针访问对象的成员的时候,编译器会做编译检查.

         id指针调用指针指向的对象的方法的时候.编译器不做任何检查 直接通过.

         id指针的缺点: 不能使用->访问属性 也不能使用点语法.

         instancetype: 只能做为方法的返回值.代表返回当前类的对象.

  • 引用计数器  

         1). 每1个对象都有1个属性.叫做retainCount.叫做引用计数器. 类型是unsigned long 占据8个字节.

             引用计数器的作用: 用来记录当前这个对象有多少个人在使用它.     

             默认情况下,创建1个对象出来 这个对象的引用计数器的默认值是1.

         2). 当多1个人使用这个对象的时候.应该先让这个对象的引用计数器的值+1 代表这个对象多1个人使用.

         3). 当这个对象少1个人使用的时候.应该先让这个对象的引用计数器的值-1 代表这个对象少1个人使用.

         4). 当这个对象的引用计数器变为0的时候.代表这个对象无人使用. 这个时候系统就会自动回收这个对象.

  • 如何操作引用计数器.

         1). 为对象发送1条retain消息. 对象的引用计数器就会加1. 当多1个人使用对象的时候才发.

         2). 为对象发送1条release消息.对象的引用计数器就会减1. 当少1个人使用对象的时候才发.

         3). 为对象发送1条retainCount消息. 就可以去到对象的引用计数器的值.

         就这样++ -- 当对象的引用计数器变为0的时候,对象就会被系统立即回收.

         在对象被回收的时候.会自动调用对象的dealloc方法.

  • [super dealloc]写在最后一句。

    原因:你所创建的每个类都是从父类,根类继承来的,有很多实例变量也会继承过来,这部分变量有时候会在你的程序内使用,它们不会自动释放内存,你需要调用父类的 dealloc方法来释放,然而在此之前你需要先把自己所写类中的变量内存先释放掉,否则就会造成你本类中的内存积压,造成泄漏

  •  野指针

         C语言中的野指针: 定义1个指针变量.没有初始化.这个指针变量的值是1个垃圾值,指向1块随机的空间.这个指针就叫做野指针.

         OC中的野指针: 指针指向的对象已经被回收了.这样的指针就叫做野指针.

  •  回收对象:

         所谓的对象的回收,指的是对象占用的空间可以分配给别人.

         当这个对象占用的空间没有分配给别人之前 其实对象数据还在. 

  •  僵尸对象

        1个已经被释放的对象,但是这个对象所占的空间还没有分配给别人.这样的对象叫做僵尸对象.

  • 内存泄露.

         指的是1个对象没有被及时的回收.在该回收的时候而没有被回收

         一直驻留在内存中,直到程序结束的时候才回收. 

  •  错误代码写法:

- (void)setCar:(Car *)car

     {

        _car = [car retain];

     }

     - (void)dealloc

     {

        [_car release];

        [super dealloc];

     }

当属性是1个OC对象的时候,setter方法照着上面那样写,其实还是有Bug的.

     当为对象的这个属性多次赋值的时候.就会发生内存泄露.

     发生泄露的原因: 当为属性赋值的时候, 代表旧对象少1个人用.新对象多1个人使用.

     应该relase旧的 retain新的.

     - (void)setCar:(Car *)car

     {

         [_car release];

         _car = [car retain];

     }

  • 在MRC的开发模式下.1个类的属性如果是1个OC对象类型的.那么这个属性的setter方法就应该按照下面的格式写.  

         - (void)setCar:(Car *)car

         {

             if(_car != car)

             {

                [_car release];

                _car = [car retain];

             }

         }

         还要重写dealloc方法.

         - (void)dealloc

         {

            [_car release];

            [super delloc];

         }

         如果属性的类型不是OC对象类型的.不需要像上面那样写. 还是像之前那样写就OK了.

  • 介绍一下@property的四组参数.

             a. 与多线程相关的两个参数.

                atomic、nonatomic.

             b. 与生成的setter方法的实现相关的参数.

                assign、retain.

             c. 与生成只读、读写相关的参数       

                readonly readwrite

             d. 是与生成的getter setter方法名字相关的参数.

                getter  setter 

  •  介绍与多线程相关的参数.

         atomic: 默认值. 如果写atomic,这个时候生成的setter方法的代码就会被加上一把线程安全锁.

                 特点: 安全、效率低下.

         nonatomic: 如果写nonatomic 这个时候生成的setter方法的代码就不会加线程安全锁.

                 特点: 不安全,但是效率高.

         建议: 要效率. 选择使用nonatomic  在没有讲解多线程的知识以前 统统使用nonatomic

  • 与生成的setter方法的实现相关的参数.

         assign: 默认值 生成的setter方法的实现就是直接赋值.

         retain: 生成的setter方法的实现就是标准的MRC内存管理代码.

                 也就是. 先判断新旧对象是否为同1个对象 如果不是 release旧的   retain新的.

         当属性的类型是OC对象类型的时候,那么就使用retain

         当属性的类型是非OC对象的时候,使用assign.

         千万注意:

         retain参数.只是生成标准的setter方法为标准的MRC内存管理代码 不会自动的再dealloc中生成relase的代码.

         所以, 我们还要自己手动的在dealloc中release

     
  • 与生成只读、读写的封装.

         readwrite: 默认值.代表同时生成getter setter

         readonly: 只会生成getter 不会生成setter

     
  • @class与#import的区别

         1). #import是将指定的文件的内容拷贝到写指令的地方.

         2). @class 并不会拷贝任何内容. 只是告诉编译器,这是1个类,这样编译器在编译的时候才可以知道这是1个类.

     
  • 1. 当两个对象相互引用的时候.

         A对象的属性是B对象  B对象的属性是A对象.

         这个时候 如果两边都使用retain 那么就会发生内存泄露.

      2. 解决方案: 1端使用retain 另外1端使用assign 使用assign的那1端在dealloc中不再需要release了.

     

     

 

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 0
博文 31
码字总数 24142
×
盘盘的灰灰
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: