码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-04-24 09:19:27      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:object   ios   内存管理   

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

手动内存管理

*为什么要学习内存管理?

①由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的。

②当我们对Objective-C 的内存管理机制琢磨不透时,编写的程序经常内存泄漏或崩溃。

③当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。

*Object-C内存管理范围

只管理任何继承了NSObject的对象,不管理其他基本数据类型(int、char、float、double、struct、enum等)。

*手动内存管理解决两个问题

①避免野指针操作

②防止内存泄露

1.认识内存管理基本概念

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

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

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

④引用计数器:(int类型,占用4个存储空间)。每个对象都有一个引用计数器,对象诞生时,count=1;当count=0的时候,对象将被销毁(回收)。

retainCount:返回对象引用计数器的值,查看有多少个指针指向这个对象。

⑥retain:返回值为当前对象,count = 引用计数器 + 1;当给对象发送一条retain消息时,引用计数器做加1操作

⑦release:无返回值,count = 引用计数器 - 1;当给对象发送一条release消息, 对象的引用计数器做减1 操作,当引用计数器 = 0,系统自动回收对象。

⑧当引用计数器 = 0时:系统自动给对象发送一条dealloc方法,通知对象将被销毁,其占用内存将被回收,指向其指针没有处理,指针的值还存在则变成野指针。

⑨alloc、new、copy创建新对象,新对象的引用计数器的值默认为1

2.内存管理原则

①在对象中,只要出现了new、alloc、retain,就一定要出现一个release进行配对

②谁创建对象,当其以后不再使用,其release

③谁使用已创建对象,其retain一下,当期以后不再使用,其release

实例示范: 

<span style="font-size:12px;">#import <Foundation/Foundation.h>
#import "ClassRoom.h"
int main(int argc, const char * argv[]) {
    ClassRoom *student1 = [[ClassRoom alloc]init];//Student1使用了alloc,最后要strdent1调用release
    NSLog(@"student1使用alloc后,引用计数器为:%zd",[student1 retainCount]);
    ClassRoom *student2 = [student1 retain];//Student2使用了retain,Student2不再使用,Student2要release
    NSLog(@"student1使用retain后,引用计数器为:%zd",[student1 retainCount]);
    [student2 release];//Student2发送release消息,之后Student2不再使用对象
    [student1 release];//Student1发送release消息,之后Student1不再使用对象
    
    return 0;
}</span>
Classroom类重写了dealloc方法如下

- (void) dealloc
{
    NSLog(@"对象被释放");
    [super dealloc];
}
结果输出: 
2015-04-23 21:52:14.914 04-内存管理[689:48749] student1使用alloc后,引用计数器为:1
2015-04-23 21:52:14.915 04-内存管理[689:48749] student1使用retain后,引用计数器为:2
2015-04-23 21:52:14.916 04-内存管理[689:48749] 对象被释放

3.对象组合的内存管理

学生、书都是OC对象,当学生拥有一本书。

学生与书采用组合关系,关键在于学生setBook、dealloc方法的实现。

set模型

- (void)setBook:(Book *)book
{
    if (_book != book) {
        [_book release];
        _book = [book retain];
    }
}

dealloc模型

- (void)dealloc
{
    [_book release];
    [super dealloc];
}

实例示范: 

main.m文件

#import <Foundation/Foundation.h>
#import "Student.h"
#import "Book.h"
int main(int argc, const char * argv[]) {
    Student *student1 = [[Student alloc]init];
    student1.name = @"张三";
    NSLog(@"学生:%@ 被创建,其引用计数器为:%zd",student1.name,[student1 retainCount]);
    
    Book *book =[[Book alloc]init];
    book.name = @"读者";
    NSLog(@"《%@》被创建,其引用计数器为:%zd",book.name,[book retainCount]);
    student1.book = book;
    NSLog(@"《%@》被学生:%@ 使用,其引用计数器为:%zd",book.name,student1.name,[book retainCount]);
    
    Book *book1 = [[Book alloc]init];
    book1.name = @"亮剑";
    NSLog(@"《%@》被创建,其引用计数器为:%zd",book1.name,[book1 retainCount]);
    student1.book = book1;
    
    NSLog(@"《%@》被学生:%@ 使用,其引用计数器为:%zd",book1.name,student1.name,[book1 retainCount]);
    NSLog(@"%@ 使用《%@》,丢弃《%@》,《%@》引用计数器为:%zd",student1.name,book1.name,book.name,book.name,[book retainCount]);
    
    [book1 release];//book1使用alloc一次,所以要release一次
    [book release];//book使用alloc一次,所以要release一次
    [student1 release];//student1使用alloc一次,所以要release一次
    return 0;
}
Book.h文件

#import <Foundation/Foundation.h>

@interface Book : NSObject
{
    @protected NSString *_name;
}
- (void) setName:(NSString *)name;
- (NSString *)name;
@end

Book.m文件

#import "Book.h"

@implementation Book
-(void)setName:(NSString *)name
{
    if (_name !=name) {
        [_name release];
        _name = [name retain];
    }
}
- (NSString *)name
{
    return _name;
}

-(void)dealloc
{
    [_name release];
    [super dealloc];
    NSLog(@"《%@》被销毁,释放内存",_name);
}
@end

Student.h文件

#import <Foundation/Foundation.h>
@class Book;
@interface Student : NSObject
{
    NSString *_name;
    Book *_book;
}
-(void) setName:(NSString *)name;
-(void) setBook:(Book *)book;
-(NSString *) name;
@end

Student.m文件

#import "Student.h"
#import "Book.h"
@implementation Student
- (void) setName:(NSString *)name
{
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}

- (void)setBook:(Book *)book
{
    if (_book != book) {
        [_book release];
        _book = [book retain];
    }
}

- (NSString *)name
{
    return _name;
}
- (void)dealloc
{
    [_name retain];
    [_book release];
    NSLog(@"%@被销毁,释放内存",_name);
    [super dealloc];
}
@end

结果输出: 

2015-04-23 23:13:03.247 04-内存管理[1278:74338] 学生:张三 被创建,其引用计数器为:1
2015-04-23 23:13:03.248 04-内存管理[1278:74338] 《读者》被创建,其引用计数器为:1
2015-04-23 23:13:03.248 04-内存管理[1278:74338] 《读者》被学生:张三 使用,其引用计数器为:2
2015-04-23 23:13:03.248 04-内存管理[1278:74338] 《亮剑》被创建,其引用计数器为:1
2015-04-23 23:13:03.248 04-内存管理[1278:74338] 《亮剑》被学生:张三 使用,其引用计数器为:2
2015-04-23 23:13:03.249 04-内存管理[1278:74338] 张三 使用《亮剑》,丢弃《读者》,《读者》引用计数器为:1
2015-04-23 23:13:03.249 04-内存管理[1278:74338] 《读者》被销毁,释放内存
2015-04-23 23:13:03.249 04-内存管理[1278:74338] 《亮剑》被销毁,释放内存
2015-04-23 23:13:03.249 04-内存管理[1278:74338] 张三被销毁,释放内存
4.autorelease的基本用法
①autorelease是半自动回收释放内存的对象方法,是将对象放到自动释放池中,当自动释放池被销毁时,所有使用autorelease的OC对象都做一次release操作。

②autorelease是对象方法,返回值为OC对象,调用完autorelease后,对象引用计数器不变。
5.autorelease的优点
①不用关注对象什么时候被是否

②不用考虑何时写release

6.autorelease使用情况

占用内存大的对象,不能随意使用autorelease

7.autorelease常见错误写法

①对象调用autorelease后,又调用release

②连续多次调用autorelease

 //常见错误1
    @autoreleasepool {
        Student *stu = [[[Student alloc]init]autorelease];
        [stu release];
    }
    //常见错误2
    @autoreleasepool {
        Student *stu = [[[Student alloc]init]autorelease];
        Student *stu1 = [stu autorelease];
    }

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

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

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

 * copy  : release旧值,copy新值

 2.是否要生成set方法

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

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

 3.多线程管理

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

 * atomic   : 性能低(默认)

 4.setter和getter方法的名称

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

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

以上实例代码修改如下示范: 

main.m文件

#import <Foundation/Foundation.h>
#import "Student.h"
#import "Book.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Student *student1 = [[[Student alloc]init]autorelease];
        student1.name = @"张三";
        NSLog(@"学生:%@ 被创建,其引用计数器为:%zd",student1.name,[student1 retainCount]);
        
        Book *book =[[[Book alloc]init]autorelease];
        book.name = @"读者";
        NSLog(@"《%@》被创建,其引用计数器为:%zd",book.name,[book retainCount]);
        student1.book = book;
        NSLog(@"《%@》被学生:%@ 使用,其引用计数器为:%zd",book.name,student1.name,[book retainCount]);
        
        Book *book1 = [[[Book alloc]init]autorelease];
        book1.name = @"亮剑";
        NSLog(@"《%@》被创建,其引用计数器为:%zd",book1.name,[book1 retainCount]);
        student1.book = book1;
        
        NSLog(@"《%@》被学生:%@ 使用,其引用计数器为:%zd",book1.name,student1.name,[book1 retainCount]);
        NSLog(@"%@ 使用《%@》,丢弃《%@》,《%@》引用计数器为:%zd",student1.name,book1.name,book.name,book.name,[book retainCount]);
    }
   
    return 0;
}

Book.h文件

#import <Foundation/Foundation.h>

@interface Book : NSObject
@property(retain,readwrite,nonatomic) NSString *name;
@end

Book.m文件
#import "Book.h"

@implementation Book
- (void)dealloc
{
    NSLog(@"《%@》被释放,内存回收",_name);
    [super dealloc];
}
@end

Student.h文件

#import <Foundation/Foundation.h>
@class Book;
@interface Student : NSObject
@property(retain,readwrite,nonatomic) NSString *name;
@property(retain,readwrite,nonatomic) Book *book;
@end

Student.m文件

#import "Student.h"
#import "Book.h"
@implementation Student
- (void)dealloc
{
    [_book release];
    NSLog(@"学生:%@被释放,内存回收",_name);
    [super dealloc];
}
@end
结果输出: 
2015-04-23 23:54:53.554 04-内存管理[1606:87943] 学生:张三 被创建,其引用计数器为:1
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《读者》被创建,其引用计数器为:1
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《读者》被学生:张三 使用,其引用计数器为:2
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《亮剑》被创建,其引用计数器为:1
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《亮剑》被学生:张三 使用,其引用计数器为:2
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 张三 使用《亮剑》,丢弃《读者》,《读者》引用计数器为:1
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《读者》被释放,内存回收
2015-04-23 23:54:53.556 04-内存管理[1606:87943] 《亮剑》被释放,内存回收
2015-04-23 23:54:53.557 04-内存管理[1606:87943] 学生:张三被释放,内存回收

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

标签:object   ios   内存管理   

原文地址:http://blog.csdn.net/h302849781/article/details/45225807

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!