OC基础-内存管理

来源:互联网 发布:excel数据分行显示 编辑:程序博客网 时间:2024/05/08 04:53

<1>内存管理的概念:由于移动设备的内容极其有限,所以对其中无用的内存空间要进行及时回收,这称为内存管理。

内存管理的范围:所有继承至NSObject的对象,其中基本数据类型由系统自动进行管理。

内存管理的原理:当在栈区定义类的实例变量后,该变量就是该实例变量的一个所有者。实例化的类对象中有retainCount变量,

称为对象的引用计数器。当引用计数器为0时,就会调用对象的dealloc方法进行对象内存空间的释放。

内存管理的分类:(1)ARC(AutoReferenceCounting):自动内存管理;(2)MRC(ManualReferenceCounting):手动内存管理;

在MRC下,可以通过对象的retain方法使retainCount增加1,release方法使retainCount减少1;当对象释放其所占用的内存空间时,

会自动调用自身的dealloc方法,可以在NSObject中重写dealloc方法。

<2>内存管理的原则:(1)谁创建,谁release;(2)谁retain,谁release。(2)只要存在对象的所有者,对象就不会被回收。

内存管理研究的内容:(1)野指针。当指针变量未初始化,或者指针变量所指向的内存空间被释放时,都会出现野指针。(2)内存泄露:

栈区的变量已经释放,而堆区的内存空间未释放时,就会出现内存泄露。

<3>单个对象的内存管理:nil:指向实例对象;Nil:指向类对象;null:指向实例对象,用在不能使用nil的场所。

给nil发送任何消息都没有效果,但能通过编译器检查。

单个对象内存泄露的情况:(1)创建完成后,没有release;(2)没有遵守内存管理的原则;(3)不当的使用了nil;(4)在函数中retain.

<4>多个对象的内存管理:依赖关系的两个对象,其正确的属性setter方法如下:

@interfance Car:NSObject


@end

@interface Person:NSObject

{Car *_car;}

-(void)setCar:(Car *)car;

@end

@implementation

-(void)setCar:(Car *)car{

if(_car != car){//避免出现僵尸对象复活的错误

[_car release];//避免出现内存泄露

_car = [car retain];//避免出现僵尸对象引用的错误

}

}

@end

<5>@property的参数有三种:

(1)原子性。

atomic:对属性加锁,多线程安全,是property的默认值;nonatomic:对属性不加锁,多线程

不安全,但速度快;

(2)读写性。

readwrite:具有完整的setter和getter方法;

readonly:只有getter方法;

(3)setter方法的处理:

assign:简单地直接赋值,是property的默认方法;

retain:对实例变量先release,再retain;

copy:对实例变量先release,在retain;

可以在@property的参数中给setter或者getter方法制定别名,如

@interface Person :NSObject

@property (nonatomic,assign ,setter = isSolider: ) BOOL solider;//指定setter方法别名为isSolider;

@end

Person *p = [Person new];

[p isSolider] = YES;//在main函数中使用isSolider方法对属性进行赋值;

<6>@class的应用:简单的引用类,告诉编译器一个类对象,并不进行类属性和方法的检查。

使用注意:(1)在.h文件中 声明@class XX;(2)在.m文件中,引用#import “XX.h”;

特殊用法:可以解决#import循环引用的问题;

@class和#import的区别:

(1)作用上:@class进行类的简单引用,而#import则是把引用文件拷贝到它所在的位置;

(2)效率上:@class引用避免了引用文件修改时的及时更新,效率较高;

<7>循环retain的问题:当两个对象循环retain时,会导致内存泄露。

防止方法:(1)在执行结束时,让其中某个对象再release一次;

(2)循环retain的两方,一端使用assign,一端使用retain;

<8>NSString类的内存管理问题:用@”XX“,[NSString StringWithString:@“XX”],[[NSString alloc] init]方法定义的字符串都是

存在内存中的常量区(数据区),当在栈区定义新的字符串变量时,如果在常量区中存在,则系统不会再次分配空间,而是会将变量指向已经

存在的变量;

用[NSString StringWithFormat:@“”]方法定义的字符串变量存放在堆区,需要对其进行内存释放;

<9>autorelease的基本使用。

(1)特殊的栈结构;

(2)对象调用autorelease方法时,会被放在栈顶;

(3)当内存池排干(drain)时,会对其中的对象发送release消息。

其中内存管理的几个实例代码如下:

(1)

#import <Foundation/Foundation.h>@interface Person : NSObject-(void)eat;@end#import "Person.h"@implementation Person-(void)dealloc{    NSLog(@"人已经被处理了");    [super dealloc];}-(void)eat{    NSLog(@"人在吃饭");}@end#import <Foundation/Foundation.h>#import "Person.h"//验证内存管理的原则:谁retain,谁releaseint main(int argc, const char * argv[]) {    @autoreleasepool {        Person *p = [Person new];        NSLog(@"retainCount = %ld",[p retainCount]);        Person *p1 = [p retain];        NSLog(@"retainCount = %ld",[p retainCount]);        [p1 release];        [p1 eat];        NSLog(@"retainCount = %ld",[p retainCount]);        [p release];        [p eat];    }    return 0;}
2
<p style="margin-top: 0px; margin-bottom: 0px; font-size: 13px; line-height: normal; font-family: Menlo; color: rgb(228, 68, 72);"><pre name="code" class="objc">#import <Foundation/Foundation.h>#include "Car.h"@interface Person : NSObject{    Car *_car;}-(void)setCar:(Car *) car;-(void)drive;@end#import "Person.h"@implementation Person-(void)setCar:(Car *) car{    if (_car != car) {        [_car release];        _car = [car retain];    }}-(void)drive{    [_car run];}-(void)dealloc{    [_car release];    NSLog(@"人已经挂了");    [super dealloc];}@end#import <Foundation/Foundation.h>@interface Car : NSObject@property int speed;-(void)run;@end#import "Car.h"@implementation Car@synthesize speed;-(void)run{    NSLog(@"车以%d的速度奔跑!",self.speed);}-(void)dealloc{    NSLog(@"车已经挂了");    [super dealloc];}@end//关联对象的内存管理#import <Foundation/Foundation.h>#import "Person.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        Person *p = [Person new];        Car *car = [Car new];        car.speed = 18;        [p setCar:car];        [car release];//清除car空间        [p drive];//        [p release];//清除person空间                    }    return 0;}
3

<pre name="code" class="objc" style="color: rgb(228, 68, 72); font-size: 13px;"><pre name="code" class="objc">#import <Foundation/Foundation.h>@class Person;@interface Dog : NSObject@property (nonatomic,assign) Person *owner;@end#import "Dog.h"@implementation Dog-(void)dealloc{   // [_owner release];    NSLog(@"dog dealloc");    [super dealloc];}@end#import <Foundation/Foundation.h>#import "Dog.h"@interface Person : NSObject@property (nonatomic,retain)Dog *dog;@end#import "Person.h"@implementation Person-(void)dealloc{    [_dog release];    NSLog(@"Person dealloc");    [super dealloc];}@end//@class避免循环引用#import <Foundation/Foundation.h>#import "Person.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        Person *p = [Person new];        Dog *d = [Dog new];        p.dog = d;        d.owner = p;                [p release];        [d release];    }    return 0;}


<p style="margin-top: 0px; margin-bottom: 0px; font-size: 13px; line-height: normal; font-family: Menlo; color: rgb(228, 68, 72);"></p>

0 0
原创粉丝点击