Objective-C:07_内存管理

基本原理:

    1、什么是内存管理

-》移动设备的内存极其有限,每个app所能占用的内存是有限制的

-》当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要在使用的内存空间,比如回收一些不需要使用的对象、变量等

-》管理范围:任何继承了NSObject的对象。对其他基本数据类型(int、char、float、double、struct、enum等)无效

局部变量都放在了内存中的栈空间中,对象放在堆空间中

堆空间中的东西是动态分配的,需要我们手动回收。栈空间不用我们自己管

 2、对象的基本结构

每个OC对象都有自己的引用计数器,是一个整数,表示"对象被引用的次数",即有多少人正在使用这个OC对象。(分配4个字节的存储空间存放引用计数器)。当对象刚刚产生的时候引用计数器是1

    3、引用计数器的作用

当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认是1

 当一个对象的引用计数器值为0是,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出。

    4、引用计数器的操作

   -》给对象发送一条retain消息,可以使引用计数器值 +1 (retain方法返回对象本身)

        -》给对象发送一条release消息,可以使引用计数器值 -1 (没有返回值)

        -》可以给对象发送 retainCount消息,获得当前的引用计数器值

关闭ARC(Automatic Reference Counting):

选中项目名称→Building Settings→Levels→Apple LLVM 6.0 -Language -Objective C将下面的YES改为no

 NSUInteger:相当于long,输出的时候占位符使用%ld

 僵尸对象:引用计数器变成0的对象,将不能使用,称为僵尸对象

    野指针:指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错

    空指针:没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错

错误:EXC_BAD_ACCESS:访问了一块坏的内存(已经被回收、已经不可用的内存);

为了防止访问坏内存的错误,我们可以在对象的计数器的值减为0之后,将指针赋空值

   p=nil;//将指针p变成空指针

    OC中不存在空指针错误,给空指针发送消息,不会报错

  -[Person setAge:]: message sent to deallocated instance 0x100202230

        给已经释放的对象发送了一条setAge:消息

 

    5、对象的销毁

-》当一个对象的引用计数器值为0时,那么他将被销毁,其占用的内存被系统回收

-》当一个对象被销毁时,系统会自动向对象发送一条dealloc消息

-》一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言

-》一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用

-》不要直接调用dealloc方法

-》一旦对象被回收,它占用的内存就不能再用,坚持使用会导致程序崩溃(野指针错误)

内存管理原则

对对象进行一次retain,那么使用结束的时候就要release

谁创建,谁release。如果你通过alloc、new创建一个对象,那么你必须调用release

谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release

你想使用(占用)某个对象,就应该让对象的计数器+1(让对象做一次retain操作)

你不想再使用(占用)某个对象,就应该让对象的设计器-1(让对象做一次release)

在类的实现中获取成员变量值方法:

_speed:直接访问成员变量

self->_speed:直接访问成员变量

self.speed:get方法

[self speed]:get方法

    内存管理代码规范:

        1、只要调用了alloc,必须有release(aotorelease)

               如果对象不是通过alloc产生的,就不需要release

        2、set方法的代码规范

                -》基本数据类型:直接赋值

                    - (void)setAge:(int)age

                    {

                        _age=age;

                    }

                -》OC对象类型

                    - (void)setCar:(Car *)car

                    {

                        //1、判断是不是新传进来的对象

                        if(car != _car)

                        {

                            //2、对旧对象做一次release

                            [_car release];

                            //3、对新对象做一次retain

                            _car = [car retain];

                        }

                    }

 

        3、dealloc方法的代码规范

               -》一定要[super dealloc],而且要放到最后面

               -》对self(当前)所拥有的其他对象做一次release

            - (void)dealloc

            {

                [_car release];

                [super dealloc];

            }

@property的内存管理

 @property (retain) Book *book;

    生成的set方法如下:

          - (void)setBook:(Book *)book

{

    if(_book != book)

    {

        [_book release];

        _book = [book retain];

    }

}

1、set方法内存管理相关参数:

       retain :release旧值,retain新值(适用于OC对象类型)

       assign:直接赋值(默认,适用于非OC对象类型)

       copy   :release旧值,copy新值

 

    2、是否要生成set方法

        readwrite:同时生成setter和getter的声明、实现(默认)

        readonly :只会生成getter的声明、实现

 

    3、多线程管理

nonatomic:生成set方法的时候不要加多线程代码。性能高(一般就用这个)

 atomic       :生成set方法的时候加多线程代码。性能低(默认)

 

    4、setter和getter方法的名称    

            setter:决定了set方法的名称,一定要有一个冒号(不常用)

            getter:决定了get方法的名称  (一般用在BOOL类型)      

        @property int age;生成的方法名为:age,setAge:

        @property (getter=abc , setter=setAbc: ) int age;

            生成的方法名:get方法:abc

                                    set方法:setAbc:

         

          long表示时间类型的时候,是从1970-01-01 00:00:00开始,一共过了多少毫秒

循环引用:

涉及到循环引用(你中有我,我中有你),添加引用的时候使用@class  类名

1、@class的作用:仅仅告诉编译器,某个名称是一个类

             @class Card;//仅仅是告诉编译器,Card是一个类

 

    2、开发中引用一个类的规范

        -》在 .h 文件中用@class来声明类

        -》在 .m 文件中用#import来包含类的所有东西

        使用@class可以提高编译器编译效率(当一个类被多个类引用的时候,如果类发生变化,那么需要重新拷贝)

3、两端循环引用解决方案:

        -》一端用retain

        -》一端用assign

autorelease:半自动释放

@autoreleasepool

 {//{ 开始代表创建了释放池

        Person *p = [[[Person alloc] init] autorelease];

        p.age = 19;

    }// }结束代表销毁释放池

注意:@autorelease是可以嵌套的,是以栈(先进后出)的方式存储的

1、autorelease的基本用法

-》会返回对象本身

-》会将对象放到一个自动释放池中

-》当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

-》Person *p = [[[Person alloc] init] autorelease]; 调用完autorelease方法后,对象的计数器不变

2、autorelease的好处

-》不用在关心对象释放的时间

-》不用再关系什么时候调用release

3、autorelease的使用注意

-》占用内存较大的对象不要随便使用autorelease

-》占用内存较小的对象使用autorelease,没有太大影响

4、错误写法

-》alloc之后调用autorelease,有又调用release

@autoreleasepool

{

Person *p = [[[Person alloc] init] autorelease];

[p release];

}

-》连续调用多次autorelease

@autoreleasepool

{

Person *p = [[[[Person alloc] init] autorelease] autorelease];

}

5、自动释放池

-》在IOS程序运行过程中,会创建无数个池子。这些池子都是以栈结果存在(先进后出)

-》当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

6、自动释放池的创建方式

-》IOS5.0前

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person *pp = [[[Person alloc] init] autorelease];

[pool release];

-》ios5.0开始

@autoreleasepool

{

Person *p = [[[[Person alloc] init] autorelease] autorelease];

}

1、系统自带的方法里没有包含alloc、new、copy,说明返回的对象都是autorelease的

NSString *str = @"13423";这种方式创建出来的字符串对象,默认就是autorelease的。不需要我们去管理内存

2、开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象

        -》创建对象时不要直接使用类名,一般用self

+ (id)person

{

return [[[self alloc] init] autorelease];

}

总结:

一、计数器的基本操作

retain:+1

release:-1

retainCount:获得计数器

二、set方法的内存管理

-》set方法的实现

- (void)setCar:(Car *)car

{

if(_car != car)

{

[_car release];

_car = [car retain];

}

}

-》dealloc方法的实现

- (void)dealloc

{

[_car release];

[super dealloc];

}

三、@property参数

-》OC对象

@property (nonatomic, retain) 类名 *属性名;

@property (nonatomic, retain) Car *car;

@property (nonatomic,retain) id car;

被retain过的属性,必须在dealloc方法中release属性

-》非OC对象

@property (nonatomic,assign) 类型名称 属性名;

@property (nonatomic,assign) int age;

四、autorelease

-》系统自带的方法中,如果不包含alloc、new、copy,那么这些方法返回的对象都已经autorelease过的

[NSString stringWithForm:.........]

[NSDate date];

-》开发中经常写一些类方法快速创建一个autorelease的对象

创建对象的时候不要直接使用类名,使用self

时间: 2024-10-05 03:10:02

Objective-C:07_内存管理的相关文章

iOS核心语言Objective C语言 —— 内存管理

本分享是面向有意向从事iOS开发的伙伴以及苹果产品的发烧友们,或者已经从事了iOS的开发者,想进一步提升者.如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步.如果您是零基础,建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在开始Objective C语言的学习,如果您遇到问题也可以与我探讨,另外将无偿分享自己整理出来的大概400G iOS学习视频及学习资料,都是干货哦!可以新浪微博私信?关注极客James,期待与您的共同学习和探讨!!由于时间有限,每天在

Objective -C Memory Management 内存管理 第一部分

Objective -C Memory Management??内存管理??第一部分 Memory management is part of a more general problem in programming called resource management. 内存管理是资源管理的一部分. Every computer system has finite resources for your program to use. These include memory, open fi

Objective C 内存管理[转]

1  配对原则 alloc – release new – release retain - release copy – release 2  new和alloc-init的区别 (1)区别只在于alloc分配内存的时候使用了zone. 这个zone是个什么呢? 它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度. (2)为什么不推荐使用new 因为若用了new,则初始化方法只能是init.这样,假如你想调用initWithFram

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

Objective-C(内存管理)

引用计数器 每个OC对象都有一个占4个字节存储空间的引用计数器 当使用或创建一个对象时,新对象的引用计数器默认是1 retain:可以使引用计数器+1 release:可以是引用计数器-1 retainCount:获得当前的引用计数器的值 当对象被销毁时,会重写dealloc方法 -(void)dealloc { // 这句必须放在最后面 [super dealloc]; } 僵尸对象:所占内存已经被回收的对象,僵尸对象不能再使用 野指针:指向僵尸对象(不可用的内存)的指针 错误:EXC_BAD

IOS学习笔记3—Objective C—简单的内存管理

今天简述一下简单的内存管理,在IOS5.0以后Apple增加了ARC机制(Automatic Reference Counting),给开发人员带来了不少的方便,但是为了能更好的理解IOS内存管理机制,还是需要对其比较了解. 1.在OC中,每个对象都有一个保留计数,创建时每个对象都有一个初始值为1的保留计数,释放时,保留计数都为0 2.创建自动释放的对象 要求以一个方法创建对象时,以自动释放的形式返回该对象是一个很好的编程实践 +(Car *)car { Car *myCar = [[Car a

iOSDay17之内存管理

1.内存管理的方式 1> iOS应用程序出现Crash(闪退),90%的原因是因为内存问题. 2> 内存问题 野指针异常:访问没有所有权的内存,如果想要安全的访问,必须确保空间还在 内存泄露:空间使用完之后没有及时释放 过度释放:对同一块存储空间释放多次,立刻crash 内存溢出:所有存储空间被占用 3> 管理内存的三种方式 垃圾回收机制:程序员只需要开辟存储空间,系统会自动回收内存.java采用的该机制 MRC:手动引用计数机制,由开发人员开辟空间,手动添加影响引用计数增加或减少的方法

Objective-C----MRC内存管理 、 自动释放池 、 面向对象三大特性及封装 、 继承 、 组合与聚合

1 MRC练习 1.1 问题 引用计数是Objective-C语言采用的一种内存管理技术,当一个对象被创建在堆上后,该对象的引用计数就自动设置为1,如果在其它对象中的对象成员需要持有这个对象时,则该对象的引用计数被加上1,此时如果该对象被释放,内存管理程序将首先把该对象的引用计数减1,然后判断该对象的引用计数是否为0,由于其它对象在持有该对象时将引用计数加了1,所以此时该对象的引用计数减1后不为0,则内存管理程序将不会释放该对象.直到持有该对象的其它对象也被释放时,该对象的引用计数再次减1,变为

<Linux内核源码>内存管理模型

题外语:本人对linux内核的了解尚浅,如果有差池欢迎指正,也欢迎提问交流! 首先要理解一下每一个进程是如何维护自己独立的寻址空间的,我的电脑里呢是8G内存空间.了解过的朋友应该都知道这是虚拟内存技术解决的这个问题,然而再linux中具体是怎样的模型解决的操作系统的这个设计需求的呢,让我们从linux源码的片段开始看吧!(以下内核源码均来自fedora21 64位系统的fc-3.19.3版本内核) <include/linux/mm_type.h>中对于物理页面的定义struct page,也