当 MyUIViewController 将其设置为 nil 时,'ControllerMediatorClass' 的实例是否不会立即被释放,因为 ControllerMediatorClass 仍充当 ClassThatDealsWithNetworking 实例的完成块?
是的。因为块会自动捕获它使用的对象,并在保留块时保留它们。
因此,由于该[ClassThatDealsWithNetworking execute:]
方法可能会保留传递给它的完成块,然后在后台执行网络调用,然后在完成后调用该块并释放该块,当该块被保留时,该块中使用的每个变量也被保留了。并且会在块被释放时被释放。
所以想象一下你的类的这个伪代码ClassThatDealsWithNetworking
:
typedef void(^NetworkingCompletionBlock)(NSDictionary* data)
@interface ClassThatDealsWithNetworking
@property(nonatomic, copy) NetworkingCompletionBlock completionBlock;
-(void)execute:(NetworkingCompletionBlock)block;
@end
@implementation ClassThatDealsWithNetworking
-(void)execute:(NetworkingCompletionBlock)block {
// make a copy of the block passed as a parameter
// so that we keep the completionBlock around inside
// the ClassThatDealsWithNetworking instance
// until the network request has finished
// ==> THIS WILL implicitly RETAIN every object used in the completionBlock
self.completionBlock = block;
...
// Then perform the network request
[NSURLConnection connectionWithRequest:... delegate:self];
...
}
-(void)connection:(NSURLConnection*)cxn didFailWithError:(NSError*)error
{
// call the completion block here
self.completionBlock(nil,error);
// then release the completionBlock
// ==> THIS WILL RELEASE every object previously implicitly retained by the completionBlock
self.completionBlock = nil;
}
-(void)connectionDidFinishLoading:(NSURLConnection*)cxn
{
NSDictionary* data = ...
// call the completion block here
self.completionBlock(data,nil);
// then release the completionBlock
// ==> THIS WILL RELEASE every object previously implicitly retained by the completionBlock
self.completionBlock = nil;
}
@end
然后,如果你这样做:
[networkCommand execute:^(NSDictionary *data)
{
self.someProperty = data;
} error:^(MyError *error)
{
NSLog(@"%@", error);
self.someProperty : nil;
}];
然后self
(您ControllerMediatorClass
在您的示例中)将被块本身隐式保留,只要该块存在,因为您self
在某处的块主体中引用。所以编译器知道在执行块时它会需要它并保留它。当块被释放时它会被隐式释放。
这确保了您在块体中使用的所有对象在块执行时仍然存在,避免崩溃。
请注意,如果您不小心,这可能会导致保留周期。例如,如果您忘记self.completionBlock = nil
在ClassThatDealsWithNetworking
类中(在委托方法或dealloc
方法中)进行 self ,则该块将永远不会被ClassThatDealsWithNetworking
实例释放,并且会继续保留self
。
For more information, read the Blocks Programming Guide in the Apple documentation.