热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

黑马程序员——OC语言——内存管理

———Java培训、Android培训、iOS培训、.Net培训、期待与您交流!———一、引用计数器每个OC对象都有自己的引用计数器,表示“对象被引用

———Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ———

一、引用计数器

每个OC对象都有自己的引用计数器,表示“对象被引用的次数”。

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

1、引用计数器的作用:


1> 当使用alloc、new或copy创建一个新对象时,新对象的引用计数器就为1。



2> 当一个对象的引用计数器的值为0时,对象所占的内存就会被系统回收。


2、引用计数器的基本操作


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

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

3> retainCount 返回当前计数器值



int main()

{

    // b-1

    Book *b = [[Book alloc] init];

    // p-1

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

    

    //p想占用b这本书

    // b-2

    [p setBook:b];

    

    // p-0

    // b-1

    [p release];

    p = nil;

    

    // b-0

    [b release];

    b = nil;

    return 0;

}



3、- dealloc方法

1> 当一个对象销毁时,系统会自动向对象发送一条dealloc的消息。(调用- dealloc方法)

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

3> 一旦对象被回收了,它占用的内存就不再可用。

- (void)dealloc  
{  NSLog(@"Person对象被回收!!!");  //super的dealloc一定要调用,而且放在最后面  [super dealloc];  

4、僵尸对象、野指针、空指针


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

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

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



二、setter方法的内存管理


1、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];

    }

}




2、dealloc方法实现



// 对当前对象所拥有的其他对象做一次release



- (void)dealloc
{



[_car release];

[super dealloc];





}



三、@property


@property 参数:

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



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

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

3> copy:release旧值,copy新值(一般用于NSString *)



2、是否要生成set方法



1> readonly:只会生成getter的声明和实现

2> readwrite:同时生成setter和getter的声明和实现



3、多线程管理



1> nonatomic:性能高(推荐)

2> atomic:性能低(默认)



4、setter和getter方法的名称



1> setter:决定了set方法的名称,一定要由冒号:

2> getter:决定了get方法的名称


@interface Person : NSObject  
  
@property int age;  
  
@property (nonatomic, readonly) double height;  
  
@property (setter = setAbc:, getter = aaa) double weight;  
  
// 返回BOOL类型的方法中,方法名一般以is开头  
@property (getter = isRich) BOOL rich;  
  
// retain参数:生成的set方法中,release旧值,retain新值  
@property (retain) Book *book;   
  

@end  



四、循环引用


A类引用了B类,同时B类也引用了A类,导致A对象和B对象永远无法释放。

解决方法:一端用retain,一端用assign。

开发中一个类引用另一个类的规范:



1> 在.h文件中用@class来声明类

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



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

格式:@class 类名;

@class和#import的区别:



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

2> 如果很多头文件都#import了同一个文件,那么一旦修改了最开始的头文件,后面所有#import引用到这个文件的所有的类都需要重新编译一遍,@class就不会有这种问题。

3> 使用了@class方式,在.m实现文件中,如果需要用到被引用的实体变量或方法,我们还需要使用#import方式引入被引用类。#import方式则不用。




五、autorelease

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

2、调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身
3、当自动释放池销毁时,会给池子里面的所有对象发送一条release消息

4、使用注意



1> 占用内存较大的对象不要随便使用autorelease(一直占着,直到pool销毁才释放,太耗内存)

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



5、常见错误



1> alloc之后调用了autorelease,又调用release,池释放时出现野指针错误

2> 连续调用autorelease,池释放时也会出现野指针错误

@autoreleasepool {          



// p-1        

// 若调用2次autorelease方法,释放池的时候会进行2次release操作,出现野指针错误          

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

// p-0        

[p release];    



} // 野指针错误  



6、系统方法

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



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

NSNumber *n = [NSNumber numberWithInt:100];

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

NSString *s2 = @"rose";



 



2> 开发中经常写一些类方法快速创建一个autorelease的对象。创建对象的时候不要直接使用类名,用self。



六、ARC


ARC的判断准则:只要没有强指针指向对象,就会释放对象

1、指针分2种



1> 强指针:默认情况下,所有的指针都是强指针 __strong

2> 弱指针:__weak

2、ARC特性

1> 不允许调用release、retain、retainCount

2> 允许重写dealloc,但不允许调用[super dealloc]

3、@property参数



1> strong:成员变量是强指针,相当于原来的retain(适用于OC对象)

2> weak:成员变量是弱指针,相当于原来的assign(还是适用于OC对象)

3> assign:适用于非OC对象类型




#import  
@class Dog;  
  
@interface Person : NSObject  
  
@property (nonatomic, weak) Dog *dog;  
@property (nonatomic, strong) NSString *name;  
  
@end  

/* 对象一被创建出来就被释放了(错误写法) 
 __weak Person *pp = [[Person alloc] init]; 
 */  

__strong Person *p = [[Person alloc] init];  
  
__weak Person *p2 = p;  
  
p = nil; // 没有强指针指向对象,对象之后被释放  
// 弱指针指向的对象都不存在了,弱指针被清空,不会发生野指针  

p2 = nil;// 弱指针不能决定是否释放对象



4、ARC的循环功能

循环引用解决方案:

ARC:

一端用strong,一端用weak

非ARC:

一端用retain,一端用assign


















推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 深入理解Java中的volatile、内存屏障与CPU指令
    本文详细探讨了Java中volatile关键字的作用机制,以及其与内存屏障和CPU指令之间的关系。通过具体示例和专业解析,帮助读者更好地理解多线程编程中的同步问题。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
author-avatar
mobiledu2502889953
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有