------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一.概述
每个对象在初始化的时候都会被分配一块内存。就像图书馆一样,每个人只借书却不还书,图书馆会因为无书可借而倒闭。然而内存也是一样,每个对象都分配一块内存,如果内存不释放的话,将会耗尽内存资源。可是怎么才能知道这块内存已经不需要使用了呢?OC有个引用计数,每个分配内存的对象都有一个相关联的整数,叫做引用计数器。当这个对象需要被访问的时候这个对象的计数器就加一,当结束访问这个对象时计数器就减一。当计数器为0的时候就销毁这个对象。
二.内存管理范围
任何继承NSObject的对象分配的内存都需要被管理,以免造成内存的泄漏。
三.内存的管理原理
1.当使用alloc,new,copy等消息创建一个对象时,这个对象的引用计数会为一。
2.给对象发送retain消息可以使得这个对象的引用计数加一。
3.给对象发送release消息可以使得这个对象的引用计数减一。
4.当这个对象的引用计数为0的时候就会发送dealloc消息销毁对象掉释放这块内存。
5.可以给对象发送retainCount消息查询这个对象的引用计数.
四.内存管理原则
1.谁创建这个对象,就负责释放这个对象。
2.谁调用了retain方法,就应该调用release方法.
代码如下
#import <Foundation/Foundation.h>
//电池类头文件
@interface Battery : NSObject
@end
//电池类实现
#import "Battery.h"
@implementation Battery
- (NSString *) description
{
return @"I'm a battery";
}
//重写dealloc方法
- (void)dealloc
{
//打印
NSLog(@"battery byebye");
//调用父类dealloc方法
[super dealloc];
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "Battery.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// 通过发送new消息创建battery对象,引用计数为1
Battery *battery = [Battery new];
// 发送retain消息,引用计数加一为2
[battery retain];
// 通过发送retaincount消息查看引用计数并打印
NSLog(@"%zi", [battery retainCount]);
// 发送release消息,引用计数减一为1
[battery release];
// 通过发送retaincount消息查看引用计数并打印
NSLog(@"%zi", [battery retainCount]);
// 发送release消息,引用计数减一为0 发送dealloc消息
[battery release];
// 此时的battery已经被销毁了 却访问这块内存 会发生野指针错误
NSLog(@"%zi", [battery retainCount]);
}
return 0;
}
五.set方法内存管理
1.谁创建这个对象,谁就负责释放这个对象。手机里面需要安装一块电池,当声明了一个电池对象并把它set进手机中,这个电池就应该被release释放掉。当需要手机发送一条消息需要看到这个电池的牌子,这个时候就会报错了,因为电池的那块内存已经被释放掉了,应该怎么解决这个问题呢?
代码如下所示:
//
// Battery.h
// 内存管理
//
// Created by AndyJerry on 14-12-9.
// Copyright (c) 2014年 AndyJerry. All rights reserved.
//
#import <Foundation/Foundation.h>
//电池类头文件
@interface Battery : NSObject
{
//电池品牌
NSString *_brand;
}
- (NSString *) brand;
- (void) setBrand:(NSString *)brand;
@end
//电池类实现
#import "Battery.h"
@implementation Battery
-(NSString *)brand
{
return _brand;
}
-(void)setBrand:(NSString *)brand
{
_brand = brand;
}
- (NSString *) description
{
return @"I'm a battery";
}
//重写dealloc方法
- (void)dealloc
{
//打印
NSLog(@"%@battery被销毁",_brand);
//调用父类dealloc方法
[super dealloc];
}
@end
#import <Foundation/Foundation.h>
//@class Battery;
#import "Battery.h"
@interface Iphone : NSObject
{
Battery * _battery;
NSString *_brand;
}
-(void) setBattery:(Battery *)battery;
-(Battery *) battery;
- (NSString *) brand;
- (void) setBrand:(NSString *)brand;
@end
#import "Iphone.h"
@implementation Iphone
-(void)setBattery:(Battery *)battery
{
//当不小心把别的battery set后dealloc却释放的是最后一个battery
//因此要判断两个battery对象是否一样
//如果不一样就把以前的对象realease
if(battery != _battery) {
[_battery release];
// set battery对象后这个battery就要被销毁
// 以后需要访问这个battery对象时候就会发生野指针错误
// 因此 给这个对象retain操作
_battery = [battery retain];
}
}
-(Battery *)battery
{
return _battery;
}
-(NSString *)brand
{
return _brand;
}
-(void)setBrand:(NSString *)brand
{
_brand = brand;
}
-(void) dealloc
{
//释放电池内存
[_battery release];
NSLog(@"%@手机被销毁", _brand);
[super dealloc];
}
-(void) say
{
NSLog(@"手机电池是:%@", _battery);
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "Battery.h"
#import "Iphone.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
//声明一个电池对象 计数器为1
Battery *battery = [[Battery alloc] init];
Battery *battery1 = [[Battery alloc] init];
//声明一个手机对象 计数器为1
Iphone *iphone = [[Iphone alloc] init];
iphone.brand = @"iphone";
battery.brand = @"iphone专用电池";
//battery 计数器为2
iphone.battery = battery;
//battery 计数器为1
[battery release];
//
//[iphone say];
battery1.brand = @"LG专用电池";
// battery计数器为0 对象被销毁 battery1对象计数器为2
iphone.battery = battery1;
// battery 对象计数器为1
[battery1 release];
// battery1计数器为0对象被销毁,iphone对象计数器为0对象被销毁
[iphone release];
}
return 0;
}
六.@property介绍
#import <Foundation/Foundation.h>
//电池类头文件
@interface Battery : NSObject
{
//电池品牌
// NSString *_brand;
}
@property (retain) NSString *brand;
//- (NSString *) brand;
//
//- (void) setBrand:(NSString *)brand;
@end
//电池类实现
#import "Battery.h"
@implementation Battery
//-(NSString *)brand
//{
// return _brand;
//}
//
//-(void)setBrand:(NSString *)brand
//{
// _brand = brand;
//}
//- (NSString *) description
//{
// return @"I'm a battery";
//}
//重写dealloc方法
- (void)dealloc
{
//打印
NSLog(@"%@battery被销毁",_brand);
//调用父类dealloc方法
[super dealloc];
}
@end
#import <Foundation/Foundation.h>
@class Battery;
@interface Iphone : NSObject
{
// Battery * _battery;
//
// NSString *_brand;
}
@property (retain) Battery * battery;
@property (retain) NSString *brand;
//-(void) setBattery:(Battery *)battery;
//
//-(Battery *) battery;
//
//- (NSString *) brand;
//
//- (void) setBrand:(NSString *)brand;
@end
#import "Iphone.h"
#import "Battery.h"
@implementation Iphone
//-(void)setBattery:(Battery *)battery
//{
// //当不小心把别的battery set后dealloc却释放的是最后一个battery
// //因此要判断两个battery对象是否一样
// //如果不一样就把以前的对象realease
// if(battery != _battery) {
// [_battery release];
// // set battery对象后这个battery就要被销毁
// // 以后需要访问这个battery对象时候就会发生野指针错误
// // 因此 给这个对象retain操作
// _battery = [battery retain];
// }
//
//}
//
//-(Battery *)battery
//{
// return _battery;
//}
//
//-(NSString *)brand
//{
// return _brand;
//}
//
//-(void)setBrand:(NSString *)brand
//{
//
// _brand = brand;
//}
-(void) dealloc
{
//释放电池内存
[_battery release];
NSLog(@"%@手机被销毁", _brand);
[super dealloc];
}
-(void) say
{
NSLog(@"手机电池是:%@", _battery);
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
//声明一个电池对象 计数器为1
Battery *battery = [[Battery alloc] init];
Battery *battery1 = [[Battery alloc] init];
//声明一个手机对象 计数器为1
Iphone *iphone = [[Iphone alloc] init];
iphone.brand = @"iphone";
battery.brand = @"iphone专用电池";
//battery 计数器为2
iphone.battery = battery;
//battery 计数器为1
[battery release];
//
//[iphone say];
battery1.brand = @"LG专用电池";
// battery计数器为0 对象被销毁 battery1对象计数器为2
iphone.battery = battery1;
// battery 对象计数器为1
[battery1 release];
// battery1计数器为0对象被销毁,iphone对象计数器为0对象被销毁
[iphone release];
}
return 0;
}
七.自动释放池(autorelease pool)
int main(int argc, const char * argv[])
{
@autoreleasepool {
//调用完autorelease方法后,对象的计数器不变
//声明一个电池对象 计数器为1
Battery *battery = [[[Battery alloc] init] autorelease];
Battery *battery1 = [[[Battery alloc] init] autorelease];
//声明一个手机对象 计数器为1
Iphone *iphone = [[[Iphone alloc] init] autorelease];
iphone.brand = @"iphone";
battery.brand = @"iphone专用电池";
iphone.battery = battery;
battery1.brand = @"LG专用电池";
iphone.battery = battery1;
}
return 0;
}