黑马程序员——OC基础---内存管理(autorelease,ARC)

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


自动释放池(autorelease pool)

自动释放池是OC⾥里⾯面的⼀一种内存⾃自动回收机制,⼀一般可以将⼀一些临时变量添加到⾃自动释放池中,统⼀一回收释放

当⾃自动释放池销毁时,池⾥里⾯面的所有对象都会调⽤用⼀一次release⽅方法 


autorelease

OC对象只需要发送⼀一条autorelease消息,就会把这个对象添加到最近的⾃自动释放池中(栈顶的释放池)

 autorelease实际上只是把对release的调⽤用延迟了,对于每⼀一次autorelease,系统只是把该对象放⼊入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会被调⽤用Release 


 1.autorelease的基本用法

 1> 会将对象放到一个自动释放池中

 2> 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

 3> 会返回对象本身

 4> 调用完autorelease方法后,对象的计数器不变

 

 2.autorelease的好处

 1> 不用再关心对象释放的时间

 2> 不用再关心什么时候调用release

 

 3.autorelease的使用注意

 1> 占用内存较大的对象不要随便使用autorelease

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

 

 

 4.错误写法

 1> alloc之后调用了autorelease,又调用release

 @autoreleasepool

 {

    // 1

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

 

    // 0

    [p release];

 }

 

 2> 连续调用多次autorelease

 @autoreleasepool

 {

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

 }

 

 5.自动释放池

 1> iOS程序运行过程中,会创建无数个池子。这些池子都是以栈结构存在(先进后出)

 2> 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

 

 

 6.自动释放池的创建方式

 1> iOS 5.0

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

 

 [pool release]; // [pool drain];

 

 

 2> iOS 5.0 开始

 @autoreleasepool

 {

    

 }



示例:

#import <Foundation/Foundation.h>
#import "Person.h"

int main()
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    Person *pp = [[[Person alloc] init] autorelease];
    
    [pool release]; // [pool drain];
    
    @autoreleasepool
    {
    
        // 1
        Person *p = [[[[Person alloc] init] autorelease] autorelease];
        
        // 0
        // [p release];
    }
    
    return 0;
}


void test()
{
    @autoreleasepool
    {// { 开始代表创建了释放池
        
        // autorelease方法会返回对象本身
        // 调用完autorelease方法后,对象的计数器不变
        // autorelease会将对象放到一个自动释放池中
        // 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
        Person *p = [[[Person alloc] init] autorelease];
        
        p.age = 10;
        
        
        
        @autoreleasepool
        {
            // 1
            Person *p2 = [[[Person alloc] init] autorelease];
            p2.age = 10;
            
            
        }
        
        
        Person *p3 = [[[Person alloc] init] autorelease];
        
        
    } // } 结束代表销毁释放池
}

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, assign) int age;

@end

#import "Person.h"

@implementation Person
- (void)dealloc
{
    NSLog(@"Person---dealloc");
    
    [super dealloc];
}
@end

运行结果:



autorelease的应用示例:


1.系统自带的方法里面没有包含allocnewcopy,说明返回的对象都是autorelease

 

 2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象

 1> 创建对象时不要直接用类名,一般用self

 + (id)person

 {

    return [[[self alloc] init] autorelease];

 }


#import <Foundation/Foundation.h>
#import "Person.h"
#import "GoodPerson.h"

int main()
{
    @autoreleasepool {
        Person *p = [Person personWithAge:100];
        
        
        GoodPerson *p2 = [GoodPerson personWithAge:10];
        
        p2.money = 100;
    }
    return 0;
}

void test()
{
    Person *p = [[Person alloc] init];
    
    p.age = 200;
    
    [p release];
    
    // 包
    // Student com.mj.test
    // Student com.mj.test2
    
    // MJStudent
    
    // SBStudent
    
    // Next Step
    
    
    @autoreleasepool
    {
        //        Person *p2 = [Person person];
        //
        //        p2.age = 100;
        
        Person *p2 = [Person personWithAge:100];
        
        //        Person *p2 = [[[Person alloc] init] autorelease];
        //
        //        p2.age = 300;
        
        
        NSString *str = @"123123";
        
        NSString *str2 = [NSString stringWithFormat:@"age is %d", 10];
        
        NSNumber *num = [[NSNumber alloc] initWithInt:10];
        [num release];
        
        
        NSNumber *num2 = [NSNumber numberWithInt:100];
    }
}


#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic, assign) int age;


+ (id)person;

+ (id)personWithAge:(int)age;

@end

#import "Person.h"

@implementation Person


+ (id)person
{
    return [[[self alloc] init] autorelease];
}


+ (id)personWithAge:(int)age
{
    Person *p = [self person];
    p.age = age;
    return p;
}

- (void)dealloc
{
    NSLog(@"%d岁的人被销毁了", _age);
    
    [super dealloc];
}
@end

#import "Person.h"

@interface GoodPerson : Person

@property (nonatomic, assign) int money;

@end

#import "GoodPerson.h"

@implementation GoodPerson

@end

运行结果:







ARC


ARC,就是由编译器代码中⾃自动加⼊入了retain/release。要注意的是,ARC并不是GC,它只是⼀一种代码静态分析⼯具

 iOS 5/Mac OS X 10.7开始导⼊入,利⽤用Xcode4.2可以使⽤用该机制

 优点:

 不需要担⼼心烦⼈人的内存管理和内存泄露

 代码的总量变少了

代码效率⾼高,由于使⽤用编译器管理引⽤用计数,减少了低效代码的可能性

缺点:

要记住新的ARC规则、关键字、特性

 使⽤用⼀一些旧代码、第三⽅方代码的时候⽐比较⿇麻烦,可能要修改编译开关,XCode4.2中默认ARCYES的状态 


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

 

 1.ARC特点

 1> 不允许调用releaseretainretainCount

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

 3> @property的参数

  * strong :成员变量是强指针(适用于OC对象类型)

  * weak :成员变量是弱指针(适用于OC对象类型)

  * assign : 适用于非OC对象类型

 4> 以前的retain改为用strong

 

 指针分2种:

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

 2> 弱指针:__weak


示例:

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"

int main()
{
    Dog *d = [[Dog alloc] init];
    
    Person *p = [[Person alloc] init];
    p.dog = d;
    
    d = nil;
    
    NSLog(@"%@", p.dog);
    
    return 0;
}

void test()
{
    // 错误写法(没有意义的写法)
    __weak Person *p = [[Person alloc] init];
    
    
    NSLog(@"%@", p);
    
    NSLog(@"------------");
}

#import <Foundation/Foundation.h>

@class Dog;

@interface Person : NSObject

@property (nonatomic, strong) Dog *dog;


@property (nonatomic, strong) NSString *name;

@property (nonatomic, assign) int age;

@end

#import "Person.h"

@implementation Person

- (void)dealloc
{
    NSLog(@"Person is dealloc");
    
    // [super dealloc];
}

@end

#import <Foundation/Foundation.h>

@interface Dog : NSObject

@end

#import "Dog.h"

@implementation Dog
- (void)dealloc
{
    NSLog(@"Dog is dealloc");
}
@end

运行结果:



模型设计示例:

#import <Foundation/Foundation.h>
#import "User.h"
#import "Status.h"

int main()
{
    // 新建2个用户
    User *u = [[User alloc] init];
    u.name = @"2B";
    
    User *u2 = [[User alloc] init];
    u2.name = @"傻B";
    
    // 新建2条微博
    Status *s = [[Status alloc] init];
    s.text = @"今天天气真好!";
    s.user = u;
    
    Status *s2 = [[Status alloc] init];
    s2.text = @"今天天气真的很好!";
    s2.retweetStatus = s;
    s2.user = u2;
    
    return 0;
}

#import <Foundation/Foundation.h>

typedef enum {
    SexMan, // 男
    SexWoman // 女
} Sex;

typedef struct {
    int year;
    int month;
    int day;
} Date;

// 姓名、微博号码、密码、头像、性别、手机、生日

@interface User : NSObject

@property (nonatomic, strong) NSString *name;

@property (nonatomic, strong) NSString *account;

@property (nonatomic, strong) NSString *password;

// http://weibo.com/a.png  URL
@property (nonatomic, strong) NSString *icon;

@property (nonatomic, assign) Sex sex;

@property (nonatomic, strong) NSString *phone;

@property (nonatomic, assign) Date birthday;

@end

#import "User.h"

@implementation User
@end

#import <Foundation/Foundation.h>
#import "User.h"

// 微博内容、微博配图、发送时间、微博发送人、转发的微博、被评论数、被转发数

@interface Status : NSObject

@property (nonatomic, strong) NSString *text;

@property (nonatomic, strong) NSString *icon;


// 从1970-01-01 00:00:00 开始,一共度过了多少毫秒
@property (nonatomic, assign) long time;
//@property (nonatomic) time_t time;

@property (nonatomic, strong) User *user;

@property (nonatomic, strong) Status *retweetStatus;

@property (nonatomic, assign) int commentsCount;
@property (nonatomic, assign) int retweetsCount;

@end

#import "Status.h"

@implementation Status
@end

#import <Foundation/Foundation.h>

@interface Person : NSObject

@end

#import "Person.h"

@implementation Person
- (void)test
{
    [@"3424234" release];
    
    [@"342432" retainCount];
}
@end

运行结果:





ARC-循环引用

当两端循环引用的时候,解决方案:

 1> ARC

 1端用strong,另1端用weak

 

 2> ARC

 1端用retain,另1端用assign


示例:

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"


int main()
{
    Person *p = [[Person alloc] init];
    
    
    Dog *d = [[Dog alloc] init];
    p.dog = d;
    d.person = p;

    return 0;
}

#import <Foundation/Foundation.h>

@class Dog;

@interface Person : NSObject

@property (nonatomic, strong) Dog *dog;

@end

#import "Person.h"

@implementation Person

- (void)dealloc
{
    NSLog(@"Person--dealloc");
}

@end

#import <Foundation/Foundation.h>

@class Person;

@interface Dog : NSObject

@property (nonatomic, weak) Person *person;

@end

#import "Dog.h"

@implementation Dog
- (void)dealloc
{
    NSLog(@"Dog--dealloc");
}
@end

运行结果:









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值