ARC最佳实践

常规

基本类型变量property使用assign

@property (nonatomic, assign) int scalarInt;
@property (nonatomic, assign) CGFloat scalarFloat;
@property (nonatomic, assign) CGPoint scalarStruct;
对象的正向引用要用strong 

@property (nonatomic, strong) id childObject;


反向引用使用weak

@property (nonatomic, weak) id parentObject;
@property (nonatomic, weak) NSObject <SomeDelegate> *delegate;

所谓的正向引用和反向引用就是用来解决对象循环依赖导致内存泄露的。


图中UIViewController 对UITableView的引用是正向引用(由左上角的箭头决定),UITableView对UIViewController的引用是反向引用。如反向引用是strong的,UIViewController的retain计数就是2。当左上角的引用releaseUIViewController对象后,它的计数就是1,而不是0,导致内存泄露。所以反向引用一定要是weak的。保证内存正常释放。

block要使用copy

@property (nonatomic, copy) SomeBlockType someBlock;
为什么要用copy?当block首次创建的时候,block对象是被分配在方法栈中的。如果方法栈消失,即方法调用完毕,调用block会引起EXC_BAD_ACCESS等错误。所以要使用copy将block copy到堆中,这样block就不受方法调用影响了。如果要将block放入list中,要copy一下:

someBlockType someBlock = ^{NSLog(@"hi");};
[someArray addObject:[someBlock copy]];

在block中使用self,或者self的属性,block都会引用self。如果block对象在堆中,就会引起引用循环。所以要将反向引用设置成weak的。

SomeBlockType someBlock = ^{
    [self someMethod];// 引起反向引用self
};
SomeBlockType someBlock = ^{
    BOOL isDone = _isDone;  // _isDone是self的属性。同样引起block反向引用self对象
};

__weak SomeObjectClass *weakSelf = self;

SomeBlockType someBlock = ^{
    SomeObjectClass *strongSelf = weakSelf;
    if (strongSelf == nil)
    {
        // The original self doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
    }
    else
    {
        [strongSelf someMethod];
    }
};

SomeObjectClass *someObject = ...
__weak SomeObjectClass *weakSomeObject = someObject;// 尽管这个对象不是self,但是它和block形成了引用循环,同样需要通过__weak打破循环

someObject.completionHandler = ^{
    SomeObjectClass *strongSomeObject = weakSomeObject;
    if (strongSomeObject == nil)
    {
        // The original someObject doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
    }
    else
    {
        // okay, NOW we can do something with someObject
        [strongSomeObject someMethod];
    }
};

dealloc中写什么

删除observer

解除notification

设置非weak的反向引用为空

解除timmer

out-parameter 要加__autoreleasing修饰符

为了避免编译器偶尔不在out-parameter前插入auto release修饰符,这里建议加上。

- (BOOL)performWithError:(__autoreleasing NSError **)error
{
    // ... some error occurs ...
    if (error)
    {
        // write to the out-parameter, ARC will autorelease it
        *error = [[NSError alloc] initWithDomain:@"" 
                                            code:-1 
                                        userInfo:nil];
        return NO;
    }
    else
    {
        return YES;
    }
}

NSError __autoreleasing *error = error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK)
{
    // handle the error.
}
 





参考:

http://blog.refractalize.org/post/10476042560/copy-vs-retain-for-objective-c-blocks

http://amattn.com/2011/12/07/arc_best_practices.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值