我对 Objective-C 中的 block 使用有点困惑。我目前使用 ARC,我的应用程序中有很多 block ,目前总是引用 self
而不是它的弱引用。这可能是这些 block 保留 self
并防止它被释放的原因吗?问题是,我是否应该始终在 block 中使用 self
的 weak
引用?
-(void)handleNewerData:(NSArray *)arr
{
ProcessOperation *operation =
[[ProcessOperation alloc] initWithDataToProcess:arr
completion:^(NSMutableArray *rows) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateFeed:arr rows:rows];
});
}];
[dataProcessQueue addOperation:operation];
}
ProcessOperation.h
@interface ProcessOperation : NSOperation
{
NSMutableArray *dataArr;
NSMutableArray *rowHeightsArr;
void (^callback)(NSMutableArray *rows);
}
ProcessOperation.m
-(id)initWithDataToProcess:(NSArray *)data completion:(void (^)(NSMutableArray *rows))cb{
if(self =[super init]){
dataArr = [NSMutableArray arrayWithArray:data];
rowHeightsArr = [NSMutableArray new];
callback = cb;
}
return self;
}
- (void)main {
@autoreleasepool {
...
callback(rowHeightsArr);
}
}
最佳答案
不要把注意力集中在讨论的 strong
或 weak
部分。而是专注于循环部分。
A retain cycle 是当对象 A 保留对象 B,并且对象 B 保留对象 A 时发生的循环。在这种情况下,如果任一对象被释放:
因此,这两个对象将在程序的生命周期内一直在内存中徘徊,即使如果一切正常,它们应该被释放。
所以,我们担心的是保留循环,而创建这些循环的 block 本身并没有什么。这不是问题,例如:
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
[self doSomethingWithObject:obj];
}];
block 保留self
,但self
不保留 block 。如果释放其中一个或另一个,则不会创建循环,并且会按应有的方式释放所有内容。
你遇到麻烦的地方是这样的:
//In the interface:
@property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);
//In the implementation:
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self doSomethingWithObj:obj];
}];
现在,您的对象 (self
) 具有对 block 的显式 strong
引用。并且该 block 具有对 self
的 隐式 强引用。这是一个循环,现在两个对象都不会被正确释放。
因为在这种情况下,self
根据定义已经有一个对 block 的strong
引用,通常最容易解决对 self
进行显式弱引用以供 block 使用:
__weak MyObject *weakSelf = self;
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[weakSelf doSomethingWithObj:obj];
}];
但这不应该是您在处理调用 self
的 block 时遵循的默认模式!这应该只用于打破 self 和 block 之间的保留循环。如果你在任何地方都采用这种模式,你就会冒着将 block 传递给在 self
被释放后执行的东西的风险。
//SUSPICIOUS EXAMPLE:
__weak MyObject *weakSelf = self;
[[SomeOtherObject alloc] initWithCompletion:^{
//By the time this gets called, "weakSelf" might be nil because it's not retained!
[weakSelf doSomething];
}];
https://stackoverflow.com/questions/20030873/