黑马程序员——ios学习笔记 OC 内存管理

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

在OC中对象时存储在堆中的,系统并不会自动释放堆中的内存,而基本类型是由系统自己管理的,放在栈上。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。所以需要对分配给对象的空间进行内存管理。

OC中存在3种管理机制:手动内存管理(MRC)、自动内存管理(ARC)、垃圾回收。

手动内存管理(MRC)

在OC中内存的管理是依赖对象引用计数器来进行的:在OC中每个对象内部都有一个与之对应的整数(retainCount),叫引用计数器,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1,当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。

法则:谁创建,谁释放。retain、copy,谁释放。

@property的参数分为三类,也就是说参数最多可以有三个,中间用逗号分隔,每类参数可以从上表三类参数中人选一个。如果不进行设置或者只设置其中一类参数,程序会使用三类中的各个默认参数,默认参数:(atomic,readwrite,assign)

一般情况下如果在多线程开发中一个属性可能会被两个及两个以上的线程同时访问,此时可以考虑atomic属性,否则建议使用nonatomic,不加锁,效率较高;readwirte方法会生成getter、setter两个方法,如果使用readonly则只生成getter方法;关于set方法处理需要特别说明,假设我们定义一个属性a,这里列出三种方式的生成代码:

assign,用于基本数据类型

@property的参数分为三类,也就是说参数最多可以有三个,中间用逗号分隔,每类参数可以从上表三类参数中人选一个。如果不进行设置或者只设置其中一类参数,程序会使用三类中的各个默认参数,默认参数:(atomic,readwrite,assign)

 

一般情况下如果在多线程开发中一个属性可能会被两个及两个以上的线程同时访问,此时可以考虑atomic属性,否则建议使用nonatomic,不加锁,效率较高;readwirte方法会生成getter、setter两个方法,如果使用readonly则只生成getter方法;关于set方法处理需要特别说明,假设我们定义一个属性a,这里列出三种方式的生成代码:

 

assign,用于基本数据类型

-(void)setA:(int)a{
    _a=a;
}

retain,通常用于非字符串对象

 

-(void)setA:(Car *)a{
    if(_a!=a){
        [_a release];    //释放原来指向的对象,避免内存泄露
        _a=[a retain];   //使新指向的对象retain,即retaincount加一
    }
}

copy,通常用于字符串对象

 

-(void)setA:(NSString *)a{
    if(_a!=a){
        [_a release];        //释放原来指向的对象,避免内存泄露
        _a=[a copy];         //使新指向的对象copy,即retaincount加一
    }

在OC中有一种内存自动释放的机制叫做“自动引用计数”(或“自动释放池”),这只是一种半自动的机制,有些操作还是需要我们手动设置的。自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法。这样一来就起到了自动释放的作用,同时对象的销毁过程也得到了延迟(统一调用release方法)。

//Person.h
#import <Foundation/Foundation.h>@interface Person : NSObject
@property  NSString *name;
-(Person *)initWithName:(NSString *)name;  //自定义构造方法的申明+(Person *)personWithName:(NSString *)name;
@end

//Person.m
#import "Person.h"
@implementation Person
-(Person *)initWithName:(NSString *)name{   //自定义构造方法的实现    	
<span style="white-space:pre">	</span>if(self=[super init]){               //判断父类初始化是否成功        	
<span style="white-space:pre">		</span>self.name=name;    
<span style="white-space:pre">	</span>}    
<span style="white-space:pre">	</span>return self;
}
+(Person *)personWithName:(NSString *)name{    
Person *p=[[[Person alloc]initWithName:name] autorelease];  //调用了autorelease   
 <span style="white-space:pre">	</span>return p;
}
-(void)dealloc{                      //重写dealloc方法    
<span style="white-space:pre">	</span>NSLog(@"%@ dealloc ",self.name);    
<span style="white-space:pre">	</span>[super dealloc];
}
@end

//main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {    
<span style="white-space:pre">	</span>@autoreleasepool {        
<span style="white-space:pre">		</span>Person *p1=[[Person alloc]init];        
<span style="white-space:pre">		</span>[person1 autorelease];<span style="white-space:pre">							</span>//调用了autorelease方法后面就不需要手动调用release方法了       
<span style="white-space:pre">		</span> p1.name=@"me";<span style="white-space:pre">								</span>//由于autorelease是延迟释放,所以这里仍然可以使用
<span style="white-space:pre">		</span>person1 Person *p2=[[[Person alloc]initWithName:@"you"] autorelease];<span style="white-space:pre">	</span>//调用了autorelease方法                
<span style="white-space:pre">		</span>Person *p3=[Person personWithName:@"he"];<span style="white-space:pre">				</span>//类方法内部已经调用了autorelease,所以不需要手动释放。               
<span style="white-space:pre">		</span> Person *p4=[Person personWithName:@"her"];        
<span style="white-space:pre">		</span>[p4 retain];    
<span style="white-space:pre">	</span>}   
<span style="white-space:pre">	</span> /*结果:me deallc
	you deallc
	he deallc
     */       
 return 0;
}


自动内存管理(ARC)

__strong定义强指针、__weak定义弱指针,当没特殊说明时,系统默认为强指针。

自动内存管理的工作原理:当一个对象没有强指针指向时,该对象就会被释放,当还有弱指针指向要释放的对象,则该弱指针指向nil。故无法使用release、retain、autorelease等MRC下的方法。

总结:

Xcode默认使用自动内存管理(ARC)进行编程,当要在MRC下进行编程时,需要在xcode软件中手动进行设置。

在ARC下兼容MRC的文件需要将其compile flag设置成-fno-objc-arc。

ARC属于编译器特性,对内存进行自动管理,故优先使用ARC,但ARC实际也是通过编译器自动添加retain、release等操作进行MRC管理,故需要了解MRC的控制机制。

 


1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值