Memory management in block

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];
}


以上です。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章