常规
基本类型变量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