zoukankan      html  css  js  c++  java
  • IOS笔记-内存管理

    引言:内存管理是OC中非常重要的一块儿,在实际操作中有许多的细节需要我们去注意。李杰明老师的视频由浅到深的详细讲解了内存这个版块,并且着重强调了内存管理的重要性。在这里我也详细总结了关于内存管理的一些知识。

    管理范围:任何继承自NSObject的对象,对基本数据类型无效

    一:计数器的基本操作

    1>计数器的基本结构:引用计数器4字节

    2>引用计数器的作用

    当使用alloc(分配存储空间)、new或者copy创建了一个新对象时,新对象的引用计数器默认值就是1。

    当计数器为0时,整个程序退出。

    当计数器部位0时,占用的内存不能被回收。

    3>引用计数器的操作

    1.retainCount

     1
     2
     3
     4
    // 设计一个Person类
    Person *p = [[Person alloc]init];
    int a = [p retainCount]; // NSUInteger a = [p retainCount];
    NSLog(@"计数器:%d",a); // a = 1(默认)
     来自CODE的代码片
    retainCount.m

    retainCount:获取当前计数值

    回收:

    (1).运行中回收 (比如植物大战僵尸中的子弹,发出去就要回收)

    (2).程序退出  (mian函数没有结束,程序不会退出)

    2.重写dealloc方法(类似遗言)

    当一个对象被回收的时候,就会自动调用这个方法

     1
     2
     3
     4
     5
     6
     7
     8
    @implementation Person
    - (void)dealloc
    {
    NSLog(@"Person对象被回收")
    // super的dealloc一定要调用,而且放在最后面
    [super dealloc];
    }
    @end
     来自CODE的代码片
    dealloc.m

    3.retain、release

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
    int main()
    {
    Person *p = [[Person alloc]init];
    [p retain];
    // 有retain 就要release
    [p release];
    // 有alloc 就要release
    [p release]; // 运行中回收,调用dealloc
    p = nil; // 对象回收,指针也可以回收。
    return 0
    }
     来自CODE的代码片
    retain.m

    retain:返回对象本身,计数器+1;

    release:没有返回值,计数器-1;

    注:使用alloc,retain必须使用release

    4>僵尸对象
    当对象被回收,就是不可用内存,对象叫做僵尸对象,当我们再去访问这一块僵尸对象,就会报错。当对象被回收,指针为野指针。这一错误就称为:野指针错误。
    OC不存在空指针错误,给空指针发送消息不报错。
    [p release]; //报错
    [nil release]; //不报错
    二:set方法的内存管理
    1>多对象内存管理
    1.只要对象还在使用,这个对象就不会回收
    只要你使用对象,对象的计数器就+1
    不再使用对象,对象的计数器就减1
    2.谁创建,谁release
    如果通过alloc、new、或copy创建,就需要调用release或autorelease。

    如果没有创建,就不用(auto)release。

    3.谁retain,谁release

    总结:有始有终,有加有减

    2>set方法内存管理

    例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
    // Book类
    @interface Book:NSObject
    @end
    @implementation Book
    - (void)dealloc
    {
    NSLog(@"Book被回收了")
    [super dealloc];
    }
    @end
     
    // Person类
    @interface Person:NSObject
    {
    // Book对象
    Book *_book;
    }
    // book的set方法和get方法
    - (void)setBook:(Book *)book;
    - (Book *)book;
    @end
     
    @implementation Person
    // book的set方法和get方法
    - (void)setBook:(Book *)book
    {
    _book = [book retain];
    }
    - (Book *)book
    {
    return _book;
    }
     
    - (void)dealloc
    {
    [_book release]; // 有retain就要release
    NSLog(@"Person被回收了")
    [super dealloc];
    }
    @end
    int main()
    {
    Book *b = [[Book alloc] init]; // b = 1
    Person *b = [[Person alloc] init]; // p = 1
    // p1想占用b这本书
    [p1 setBook:b]; // b = 2;
    [b release]; // b = 1;
    b = nil;
    [p1 release]; // p1 = 0, b =0
    p1 = nil;
    return 0;
    }
     来自CODE的代码片
    多对象内存管理.m
    1.对set方法的完善:
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
    @implementation Person
    - (void)setCar:(Car *)car
    {
    if(car != car) // 防止重复定义报错
    {
    // 对当前正在使用的车(旧车)做一次release
    [_car release];
    // 对新车做一次retain操作
    _car = [car retain];
    }
    }
    @end
     来自CODE的代码片
    set方法完善.m
    2.内存管理代码规范
    1.只要调用alloc,必须有release(autorelease)
    2.set方法的代码规范:
    (1)基本数据类型:直接复制
     1
     2
     3
     4
    - (void)setAge:(int)age
    {
    _age = age;
    }
     来自CODE的代码片
    基本数据类型.m
    (2)OC对象类型
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
    @implementation Person
    - (void)setCar:(Car *)car
    {
    if(car != car) // 防止重复定义报错
    {
    // 对当前正在使用的车(旧车)做一次release
    [_car release];
    // 对新车做一次retain操作
    _car = [car retain];
    }
    }
    @end
     来自CODE的代码片
    set方法完善.m
    三:@property的内存管理
    在@property语法后面加入小括号,可以加入一些参数。例如:@property (retain) Book *book;   //retain生成的set方法里面的作用:release旧值,retain新值。
    具体的@property参数有4类
    1>内存管理相关参数
    retain:release旧值,retain新值
    assign:直接赋值(默认为assign,适用于非OC对象类型)
    copy:release旧值,copy新值
    2>是否要生成set方法
    readwrite:同时生成set、get的声明、实现(默认情况)
    readonly:只读。(只生成getting)
    3>多线程管理
    nonatomic:性能高(目前写代码必写)
    atomic:性能低(默认情况)
    4>setter 和 getter方法的名称
    (getter method)  一般用在BOOL类型
    (setter method)  这里的method要有冒号
     1
     2
     3
     4
     5
     6
     7
     8
     9
    @property (getter = isRich) BOOL rich;
    // 当遇到BOOL类型,返回BOOL类型的方法名一般以is开头
    // OC对象
    // @property (nonatomic,retain) 类名 *属性名
    @property (nonatomic,retain) Car *car;
    @property (nonatomic,retain) id car; //id类型除外
    // 非OC对象类型(intfloatenumstruct)
    // @property (nonatomic,assign) 类名 *属性名
    @property (nonatomic,assign) int age;
     来自CODE的代码片
    BOOLis.m
    注:同一类参数不可同时写(除第四类外)。
    四:循环retain 和 @class
    1>@class的作用:仅仅告诉编译器,某一个名称是一个类
    @class Person  // 仅仅告诉编译器,Person是一个类
    2>开发中引用一个类的规范
    (1)在.h文件中用@class来声明类
    (2)在.m文件中用#import来包含类的所有东西
    3>两端循环引用解决方案
    (1)一端用retain
    (2)一端用assign
    4>两种方式的区别:
    #import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息.
    例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
    #import <Foundation/Foundation.h>
     
    @class Book;
    @interface Student
    @property (retain) Book *book;
    @end
     
    #import "Student.h"
    #import "Book.h"
    @implementation Student
    - (void)dealloc {
    [_book release];
    [super dealloc];
    }
    @end
     来自CODE的代码片
    @class.m
    注意问题:为什么用@class更好
    第一:解决循环retain问题
    第二:提高性能
    五:autorelease
    1>autorelease的基本用法
    (1)会将对象放到一个自动释放池中
    (2)当自动释放池被销毁时,会对池子里面的所有对象做一次release操作。
    (3)会返回对象本身
    (4)调用完autorelease方法后,对象的计数器不变。
    2>autorelease的好处
    (1)不用再关心对象释放时间
    (2)不用再关心什么时候调用release
    3>autorelease的使用注意
    (1)占用内存较大的对象不要随便使用autorelease
    (2)占用内存较小的对象使用release没有太大影响
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    @autoreleasepool
    { // {开始代表创建了释放池
    Person *p = [[[Person alloc] init] autorelease];
    p.age = 10;
    @autoreleasepool
    {
    Person *p2 = [[[Person alloc] init] autorelease];
    p2.age = 12;
    }
    } // }结束代表释放池销毁
     来自CODE的代码片
    autorelease.m
    4>自动释放池
    (1)在ios程序运行过程中,会创建无数个池子,这些池子都是以栈的结构存在(先进后出)
    (2)当一个对象调用autorelease方法时,会将这个对象放在栈顶的释放池。
    5>自动释放池的创建方式
    (1)iOS 5.0以前
     1
     2
    NSAutoreleasepool *pool = [[NSAutoreleasepool alloc] init];
    [pool release]; // [pool drain]
     来自CODE的代码片
    autoreleasepool.m
    (2)5.0之后
    @autoreleasepool{
    }
    实例操作:
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
    @interface Person:NSObject
    + (id)person;
    + (id)personWithAge;
    @end
     
    @implementation Person
    + (id)person
    {
    return [[self alloc] autorelease];
    }
    + (id)personWithAge
    {
    Person *p = [self person];
    p.age = age;
    return p;
    }
    - (void)dealloc
    {
    NSLog(@"Person被回收了");
    [super dealloc];
    }
    @end
     
    #import <Foundation/Foundation.h>
    int main()
    {
    @autoreleasepool
    {
    // 调用简单
    Person *p = [Person person];
    p2.age = 100;
    }
     
    return 0;
    }
     来自CODE的代码片
    实例操作.m
    总结:1系统自带的方法里面没有包含alloc、new、copy,说明返回的对象都是autorelease的。
    [NSString stringWithFormat:……];
    2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象。(注:创建对象时不要直接用类名,一般用self)
  • 相关阅读:
    SQL注入实验-2021.01.24
    数据库的搭建与基本语句2021-01-24
    Linux
    磁盘配置
    在Vmware中Centos下的Hadoop环境搭建
    Linux系统(CentOS)-2021.1.19
    中间件,JavaScript,PHP及burpSuite暴力破解实验-2021.1.16
    html,css学习笔记-2021.1.15
    第一周学习视频(二)
    第一周学习视频(一)
  • 原文地址:https://www.cnblogs.com/houzhitong/p/4511726.html
Copyright © 2011-2022 走看看