非ARC开发的内存管理

一. 内存管理原则

  1. retain和release配对使用;

  2. 只要出现retain、alloc、copy中的其中一个,就要用一次release;

  3. 只要retainCount为0,系统会自动调用dealloc

  4. @property中使用的关键字

    readwrite:属性会被当成读写的,默认
    readonly:属性只可读不可写
    assign:不会使引用计数加1,常用于数值
    retain:会使引用计数加1,只在非ARC中使用
    copy:建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝
    nonatomic:非原子性访问,多线程并发访问会提高性能
    atomic:原子性访问
    strong:打开ARC时才会使用,相当于retain。
    weak:打开ARC时才会使用,相当于assign,可以把对应的指针变量置为nil。

二. 属性中没有类类型的属性的内存管理

  1. 只要遵循“创建一个对象时,必须有一次release”即可。
  2. 如下面代码
---------- 如下,Dog类中属性的类型只有int,没有类类型的属性

#import <Foundation/Foundation.h>

@interface Dog : NSObject

@property (nonatomic, assign) int age;

@end

@implementation Dog

- (void)dealloc {

    NSLog(@"%s", __func__);

    [super dealloc];
}

@end


---------- 下面是关于Dog对象的内存管理

    // 方式一
    Dog *dog1 = [[[Dog alloc] init] autorelease];
    // 使用dog
    // 使用dog代码....

    // 方式二
    Dog *dog2 = [[Dog alloc] init];
    // 使用dog
    // 使用dog代码....
    // 使用完后release
    [dog2 release];

提示:
NSArray *arr = [NSArray array]; 和 NSArray *arr = @[]; 等价,内部已经有了一个autorelease,不需要重复写release

三. 属性中有类类型的属性的内存管理

  1. 根据谁使用谁撤销的原则,在dealloc方法中必须设置类类型的属性为空,即给类类型的属性来一次release

  2. 如下代码

A. 下面是不使用@property (nonatomic, retain) 的情况

---------- 关于Dog的类如上代码,这里只写Person类,下面是不使用@property (nonatomic, retain) 的情况 

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

@interface Person : NSObject
{
    Dog *_dog;
}

- (void)setDog:(Dog *)dog;
- (Dog *)dog;
@end

@implementation Person

- (void)dealloc {
    // 必须设置为nil,相当于对self.dog一次release
    // 保证Person对象不在的时候,dog的引用计数减一,因为是Person引用了一次
    self.dog = nil;

    [super dealloc];
}

- (void)setDog:(Dog *)dog {

    if (_dog != dog) {
        [_dog release];
        _dog = [dog retain];
    }
}

- (Dog *)dog {
    return _dog;
}

@end


---------- 关于使用Person类的内存管理

    Person  *person = [[[Person alloc] init] autorelease];
    Dog *dog = [[[Dog alloc] init] autorelease];
    person.dog = dog;
    person.dog = dog;// 即使有第二次赋值,引用计数器也不会加一

    NSLog(@"person---%ld", person.retainCount);
    NSLog(@"person.dog----%ld", person.dog.retainCount);

运行结果:

这里写图片描述



B. 下面是使用@property (nonatomic, retain) 的情况
这样的好处是不用手动去写类类型的属性的setter方法
上面的Person类可以改成

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

@interface Person : NSObject

@property (nonatomic, retain) Dog *dog;

@end

@implementation Person

- (void)dealloc {
    // 必须设置为nil,相当于对self.dog一次release
    // 保证Person对象不在的时候,dog的引用计数减一,因为是Person引用了一次
    self.dog = nil;

    [super dealloc];
}

@end

修改后的运行结果一样:
这里写图片描述


四. copy属性的作用

  1. copy属性是完全把对象重新拷贝了一份,计数器从新设置为1,和之前拷贝的数据完全脱离关系

  2. 和retain一样,如果不使用@property (nonatomic, copy) 就必须自己写下面的代码

@property (nonatomic, copy) NSString *string;
 
- (NSString *) string {
  return _string;
}

- (void)setString:(NSString *)newStr {

    if (_string != newStr) {
        [_string release];
        _string = [newStr copy];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值