zoukankan      html  css  js  c++  java
  • Objective-C知识总结(3)

    手动内存管理MRC

    首先介绍一下引用计数器:用来保存当前对象有几个东西在使用它(数字)

    引用计数器的作用:用来判断对象是否应该回收内存空间(如果对象不等于nil,当引用计数器为0,此时要回收对象的内存空间)

    引用计数器的操作:

    • retain    使得引用计数器+1

    • release   使的引用计数器-1

    • retainCount  得到引用计数器的值

    如果一个对象被释放的时候,会调用该对象的dealloc方法

    注意:

    • dealloc方法是NSObject 的,一般我们要重写dealloc方法
    • 在dealloc 方法的内部,要调用 [super dealloc];

    内存管理的范围:

    • 所有的集成了NSObject的对象的内存管理

    • 基本数据类型(int double float char struct enum )的数据内存不需要我们进行管理

    内存管理的原则:

    1. 如果对象有人使用,就不应该回收  

      如果你想使用这个对象,应该让这个对象 retain一次  

      如果你不想使用这个对象了,应该让这个对象 relase一次

    2. 谁创建 谁release

    3. 谁 retain 谁 release

    内存管理研究的内容:

    1. 野指针:

        1)定义的指针变量没有初始化     2)指向的空间已经被释放

    2. 内存泄露:

      {
                   Person *p  = [Person new];
       
                   }
      /*
                   p 栈区
                   [Person new];  堆区
       
                   如果栈区的p已经释放了,而堆区的空间还没有释放,堆区的空间就被泄露了
      */

    set方法内存管理

    //  Dog* _dog;
     
    //  对于对象作为另外一个类的实例变量
     
    - (void)setDog:(Dog*)dog {
     
     //  判断对象是否是原对象
            if(_dog != dog) {
     
               //2) release旧值
               [_dog release];
     
                // retain 新的值,并且赋值给实例变量
               _dog = [dog retain];
            }
        }

    循环retain问题

    循环的retain 会导致两个对象都会内存泄露

    防止方法:

    1. 让某个对象多释放一次 (注意顺序)

    2. 一端使用 assign   一端使用retain(推荐使用)

    NSString类的内存管理问题

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            //定义字符串
            //字符串的常量池,
            //如果你需要的字符串在常量池中已经存在了,不会分配内存空间
            //使用字符串的时候,
            // @"abc"  stringWithString    alloc initWithString  都在常量区/
            
            //0x100001030 小
            NSString *str1 = @"abc";   //@"abc" 字符串的常量
            NSString *str3 = [NSString stringWithString:@"abc"];   //常量区
            NSString *str5 = [[NSString alloc] initWithString:@"abc"]; //也在常量区
            NSString *str6 = [[NSString alloc] init];//常量区
            str6 = @"abc";
    
            
            //0x100202030 大
            //如果在常量区 str2  str4 地址应该是一样的
            //实际上不一样的,所以 str2 str4都在堆区
            NSString *str2 = [NSString stringWithFormat:@"abc"];   //不是在栈区,在堆区
            NSString *str4 = [[NSString alloc] initWithFormat:@"abc"];//不是在栈区,在堆区
            
            
            //0x7fff5fbff764
            int a = 10;  //栈区
            
            NSLog(@"str1 = %@,%p,%lu",str1,str1,str1.retainCount);
            NSLog(@"str2 = %@,%p,%lu",str2,str2,str2.retainCount);
            NSLog(@"str3 = %@,%p,%lu",str3,str3,str3.retainCount);
            NSLog(@"str4 = %@,%p,%lu",str4,str4,str4.retainCount);
            NSLog(@"str5 = %@,%p,%lu",str5,str5,str5.retainCount);
            NSLog(@"str6 = %@,%p,%lu",str6,str6,str6.retainCount);
            NSLog(@"a = %p",&a);
            
            
        }
        return 0;
    }

    自动释放池 :特殊的栈结构

    特点: 

    • 对象可以加入到自动释放池中
    • 自动释放池结束的时候,会给池中的对象发送一条 release消息

    自动释放池的使用:

    1. 创建自动释放池
          @autoreleasepool {
    
          }

         2.  加入自动释放池

    /*
      在自动释放池中
      [对象  autorelease];
    */

    模拟一个Person类 类中有个一个对象方法- (void)run;

    #import <Foundation/Foundation.h>
    #import "Person.h"
    int main(int argc, const char * argv[]) {
        //1 创建自动释放池
        Person *p = [Person new];  // p  1
        @autoreleasepool {//自动释放池开始
            
            [p run];
     
            NSLog(@"%lu",p.retainCount); // 1
            
            // [p autorelease] 把对象p加入到自动释放池中
            // 注意:加入到自动释放池中以后, 引用计数不会变化
            [p autorelease];  //加入自动释放池,
            NSLog(@"%lu",p.retainCount); // 1
            
            [p run];
            
        }//自动释放池结束   [p release];
        [p run];
        return 0;
    }

     我们可以给Person添加一个类方法,让其创建完对象就加入到自动释放池中

    +(instancetype)person{
        //Person person  ---> Person
        //Stduent person ----> Student
        //创建对象
        return [[[self alloc] init] autorelease];  // 返回的时对象的空间
        // 能够帮我们把对象给加入到自动释放池
    
    }

         

  • 相关阅读:
    [Java] SSH框架笔记_框架分析+环境搭建+实例源码下载
    [JavaEE] WEB-INF有关的目录路径总结
    网站标题分隔符
    [Windows] 解决kmplayer播放rmvb文件音视不同步
    [MySQL] 数据统计 —— 按周,按月,按日分组统计数据
    [Java] JSTL格式化时间计算时差
    [C.Sharp] TimeSpan的用法,获取测试程序运行时间
    [设计模式] .NET设计模式笔记
    Spring Boot使用redis做数据缓存
    Spring Boot使用redis做数据缓存
  • 原文地址:https://www.cnblogs.com/melodyzhy/p/4678759.html
Copyright © 2011-2022 走看看