これも私にとって問題だったので、別の回答を投稿します。私は元々、ブロック内に自己参照がある場所ではblockSelfを使用する必要があると思っていました。これは当てはまりません。オブジェクト自体にブロックがある場合のみです。実際、これらの場合にblockSelfを使用すると、ブロックから結果が返される前にオブジェクトの割り当てが解除され、それを呼び出そうとするとオブジェクトがクラッシュするため、応答までselfを保持する必要があることは明らかです。戻ってくる。
最初のケースは、ブロックで参照されるブロックが含まれているために保持サイクルが発生する場合を示しています。
#import <Foundation/Foundation.h>
typedef void (^MyBlock)(void);
@interface ContainsBlock : NSObject
@property (nonatomic, copy) MyBlock block;
- (void)callblock;
@end
@implementation ContainsBlock
@synthesize block = _block;
- (id)init {
if ((self = [super init])) {
//__block ContainsBlock *blockSelf = self; // to fix use this.
self.block = ^{
NSLog(@"object is %@", self); // self retain cycle
};
}
return self;
}
- (void)dealloc {
self.block = nil;
NSLog (@"ContainsBlock"); // never called.
[super dealloc];
}
- (void)callblock {
self.block();
}
@end
int main() {
ContainsBlock *leaks = [[ContainsBlock alloc] init];
[leaks callblock];
[leaks release];
}
2番目のケースではblockSelfは必要ありません。これは、呼び出し元のオブジェクトにブロックが含まれていないため、selfを参照したときに保持サイクルが発生するためです。
#import <Foundation/Foundation.h>
typedef void (^MyBlock)(void);
@interface BlockCallingObject : NSObject
@property (copy, nonatomic) MyBlock block;
@end
@implementation BlockCallingObject
@synthesize block = _block;
- (void)dealloc {
self.block = nil;
NSLog(@"BlockCallingObject dealloc");
[super dealloc];
}
- (void)callblock {
self.block();
}
@end
@interface ObjectCallingBlockCallingObject : NSObject
@end
@implementation ObjectCallingBlockCallingObject
- (void)doneblock {
NSLog(@"block call complete");
}
- (void)dealloc {
NSLog(@"ObjectCallingBlockCallingObject dealloc");
[super dealloc];
}
- (id)init {
if ((self = [super init])) {
BlockCallingObject *myobj = [[BlockCallingObject alloc] init];
myobj.block = ^() {
[self doneblock]; // block in different object than this object, no retain cycle
};
[myobj callblock];
[myobj release];
}
return self;
}
@end
int main() {
ObjectCallingBlockCallingObject *myObj = [[ObjectCallingBlockCallingObject alloc] init];
[myObj release];
return 0;
}
self
ひっくり返すためthis
だけにプロキシを呼び出すのが好きです。JavaScriptでは、this
クロージャーを呼び出しますself
。そのため、快適でバランスが取れています。:)