黑马程序员_OC_内存管理-程序员宅基地

技术标签: OC  

一.基本原理


1. 什么是内存管理

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

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

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

 

2.  对象的基本结构


   每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象

   每个OC对象内部专门有4个字节的存储空间来存储引用计数器


二.引用计数器的基本操作


 1.方法的基本使用

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

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

 3> retainCount :获取当前的计数器

 4> dealloc

  * 当一个对象要被回收的时候,就会调用

  * 一定要调用[super dealloc],这句调用要放在最后面

 

 2.概念

 1> 僵尸对象 :所占用内存已经被回收的对象,僵尸对象不能再使用

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

 3> 空指针 :没有指向任何东西的指针(存储的东西是nilNULL0),给空指针发送消息不会报错

 


   Person *p = [[Personalloc] init];

    

    //NSUInteger c = [p retainCount];

    

    //NSLog(@"计数器:%ld", c);

    

    

    // 2 retain方法返回的是对象本身

    [pretain];

    

   // 1

    [prelease];

    

    // 0野指针:指向僵尸对象(不可用内存)的指针

    [prelease];

    

    [pretain];

    

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

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

    p.age =10;

    //[p setAge:10];

    

    // 指针p变成空指针

    //p = nil;

    

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

    // 野指针错误

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

    [prelease];

    [prelease];

    [prelease];

    [prelease];

    

    [nilrelease];


@implementation Person

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

- (void)dealloc

{

    NSLog(@"Person对象被回收");

    

    // superdealloc一定要调用,而且放在最后面

    [superdealloc];

}

@end


三.多个对象之间的内存管理


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

 

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

 

3.retain,谁release

 

4.alloc,谁release


    // b-1

   Book *b = [[Bookalloc] init];

    // p-1

   Person *p1 = [[Personalloc] init];

    

    //p1想占用b这本书

    // b-2

    [p1setBook:b];

    

    // p-0

    // b-1

    [p1release];

    p1 =nil;

    

    // b-0

    [brelease];

    b =nil;



四.set方法的内存管理


如果你有个OC对象类型的成员变量,就必须管理这个成员变量的内存。比如有个Book *_book

1.       set方法的实现

- (void)setBook:(Book *)book{

       if (book !=_book) {

           [_bookrelease];

           _book= [book retain];

       }

}

 

2.       dealloc方法的实现

- (void)dealloc {

       [_bookrelease];

       [super dealloc];

}

————————————————————————

内存管理代码规范:

 1.只要调用了alloc,必须有releaseautorelease

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

 

 2.set方法的代码规范

 1> 基本数据类型:直接复制

 - (void)setAge:(int)age

 { 

    _age = age;

 }

 

 2> OC对象类型

 - (void)setCar:(Car *)car

 {

    // 1.先判断是不是新传进来对象

    if ( car != _car )

    {

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

        [_car release];

 

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

        _car = [car retain];

    }

 }

 

 3.dealloc方法的代码规范

 1> 一定要[super dealloc],而且放到最后面

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

 - (void)dealloc

 {

    [_car release];

    [super dealloc];

 }

———————————————————————————————

 1.set方法内存管理相关的参数

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

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

 * copy   : release旧值,copy新值

 

 2.是否要生成set方法

 * readwrite : 同时生成settergetter的声明、实现(默认)

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

 

 3.多线程管理

 * nonatomic : 性能高 (一般就用这个)

 * atomic    : 性能低(默认)

 

 4.settergetter方法的名称

 * setter : 决定了set方法的名称,一定要有个冒号 :

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


———————————————————————————————

五.@property参数


1.  控制set方法的内存管理

   retain release旧值,retain新值(用于OC对象)

   assign直接赋值,不做任何内存管理(默认,用于非OC对象类型)

   copy  release旧值,copy新值(一般用于NSString *

 

2.        控制需不需生成set方法

   readwrite:同时生成set方法和get方法(默认)

   readonly :只会生成get方法

 

3.        多线程管理

   atomic   :性能低(默认)

   nonatomic:性能高

 

4.        控制set方法和get方法的名称

   setter设置set方法的名称,一定有个冒号:

   getter设置get方法的名称


六.循环引用


1.  @class

使用场景

对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类


这种代码编译会报错。当使用@class在两个类相互声明,就不会出现编译报错

   

> 用法概括

使用 @class 类名; 就可以引用一个类,说明一下它是一个类

   

>和#import的区别

》   #import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息


》  如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来讲,使用@class方式就不会出现这种问题了


》  在.m实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类

 

 

2.  循环retain

   比如A对象retain了B对象,B对象retain了A对象

   这样会导致A对象和B对象永远无法释放

 

3.  解决方案

   当两端互相引用时,应该一端用retain、一端用assign


七.autorelease


1.autorelease

   给某个对象发送一条autorelease消息时,就会将这个对象加到一个自动释放池中

   当自动释放池销毁时,会给池子里面的所有对象发送一条release消息

   调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身

   autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会被调用Release

 

2.自动释放池的创建

   ios 5.0后

@autoreleasepool

{

    // ....

}

   ios 5.0前

NSAutoreleasePool *pool = [[NSAutoreleasePoolalloc] init];

// .....

[pool release];// [pool drain];

   在程序运行过程中,可以创建多个自动释放池,它们是以栈的形式存在内存中

   OC对象只需要发送一条autorelease消息,就会把这个对象添加到最近的自动释放池中(栈顶的释放池)

 

3.应用实例

   跟release的对比

   以前:

 

Book *book = [[Bookalloc] init];

[book release];

l   现在:

Book *book = [[[Bookalloc] init]autorelease];

// 不要再调用[book release];

 

   一般可以为类添加一个快速创建对象的类方法

+ (id)book {

    return [[[Bookalloc] init]autorelease];

}

外界调用[Book book]时,根本不用考虑在什么时候释放返回的Book对象

 

4.规律

   一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease

   比如下面的对象都已经是autorelease的,不需要再release

NSNumber *n = [NSNumbernumberWithInt:100];

NSString *s = [NSStringstringWithFormat:@"jack"];

NSString *s2 =@"rose";







版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/huangchen_wyx/article/details/27960861

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范