Memory management in block
Blockの具体的な使い方は
を参考してください。
Blockの使うのは二つ形式があります。
-
- copyしてない。
- copyしてます。
copyしてない場合
この場合、blockのmemory spaceはstackにいます。何の変数でも使えます。memory leakを気にしない。
typedef void (^MyBlock)(void);
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
// HelloWorldLayer
@interface IntroLayer : CCLayer
{
}
@property (nonatomic, assign) MyBlock nocopiedBlock;
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int num;
@end
@implementation IntroLayer
-(void) onEnter
{
[super onEnter];
int localVar = 10;
self.nocopiedBlock = ^(void){
self.name = @"wang";
self.num = localVar + 100;
};
[self scheduleOnce:@selector(makeTransition:) delay:1];
}
-(void) makeTransition:(ccTime)dt
{
self.nocopiedBlock();
}
@end
ここはnocopiedBlockをassignにsetして、copyしてない。self.nocopiedBlockはonEnter scopeの全部変数を呼ばれます。self.nocopiedBlockの自身もonEnter scopeにあります。一旦onEnter以外の位置から(例えばmakeTransitionから)self.nocopiedBlockを呼んだら、落ちます。
copyしてる場合
この場合、blockのmemory spaceはstackからheapにcopyしました。memory leakを気にします。
- local変数
- local変数にcopyするので、blockに変更したら、stackにの元の変数と関係ないです。
- static/global変数
- heapにcopyしない、read/writeも出来る。
- objective c対象
- selfの変数を呼ばれたら、selfをretainされます。selfにこのblockをcopyしたので、循環参照があります。
解決方法は、
__block ClassName *selfInBlock = self; // BlockにselfInBlockを使います。
-
- 他のobjective c対象を呼ばれたら、この対象がretainされてます。blockを終わる前、この対象自動にをreleaseされます.
この場合は__blockが要らない。
例えば、
typedef void (^MyBlock)(void);
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
// HelloWorldLayer
@interface IntroLayer : CCLayer
{
}
@property (nonatomic, copy) MyBlock copiedBlock;
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int num;
@end
@implementation IntroLayer
-(void) onEnter
{
[super onEnter];
int localVar = 10;
NSArray *testArray = [NSArray array];
__block ClassName *selfInBlock = self;
self.copiedBlock = ^(void){
selfInBlock.name = @"wang";
selfInBlock.num = localVar + 100;
[testArray addObject:selfInBlock.name];
// testArray will be released automatically.
// [testArray release];
};
[self scheduleOnce:@selector(makeTransition:) delay:1];
}
-(void) makeTransition:(ccTime)dt
{
self.copiedBlock();
}
@end
use __block
もし
[testArray release];
をめんどくさいと思って、__blockを使います。
- local変数
- __blockを使ったら、blockに変更で来ます。
- objective c対象
- __blockを使ったら、この対象をretainされてないので、release必要がない。
selfじゃないobjectは__blockを使わないほうがいいです、自動にreleaseされますから。
-(void) onEnter
{
[super onEnter];
__block int localVar = 10;
// selfじゃないobjectは__blockを使わないほうがいいです、自動にreleaseされますから。
__block NSArray *testArray = [NSArray array];
__block ClassName *selfInBlock = self;
self.copiedBlock = ^(void){
selfInBlock.name = @"wang";
selfInBlock.num = localVar + 100;
localVar = 11; // localVarを変更出来る。
[testArray addObject:selfInBlock.name];
};
[self scheduleOnce:@selector(makeTransition:) delay:1];
}
以上です。