2011-02-03

『iOS 4プログラミングブック』 第5章マルチスレッド 補遺 その6



楽天BOOKSで一時売り切れになるも、再度入荷中の『iOS 4プログラミングブック』。Amazonでは相変わらず在庫切れ...

補遺その6では、ちょっと趣向を変えてサンプルコードを説明してみます。

第5章マルチスレッドのサンプルコードは、実はTumblr Image Viewerになっていたり、cocos2d for iPhoneを使っていたりする、実戦さながらのサンプルコードとなっております。

今回はcocos2dでの非同期テクスチャ読み込みについて掘り下げてみます。


cocos2dの非同期テクスチャ読み込みAPIは、読み込み終了時にtargetのselectorを呼ぶコードになっています。これBlocksだと楽になるような気がしませんか? Blockを受け取って呼び出すClassを作ってみます。

■TextureCallback.h

/*
* 「5-1 Blocksの概要」(178ページ)
* TextureCallbackクラスにより、
* cocos2dのイメージ非同期読み込み終了コールバックを、
* Blocksに結びつけることにより、より簡単にコールバックを記述できます。
*/

#import "cocos2d.h"

/*
* 「5-2-2 値としてのBlock」(184ページ)
* typedefを使用したBlocksの宣言。
*/
typedef void (^textureCallbackBlock_t)(CCTexture2D *texture);

@interface TextureCallback : NSObject
{
textureCallbackBlock_t block_;
}

/*
* イメージ非同期読み込み終了コールバックで実行されるBlockを指定。
*/
+ (id)callbackWithBlock:(textureCallbackBlock_t)block;
- (id)initWithBlock:(textureCallbackBlock_t)block;
- (void)callback:(CCTexture2D *)texture;

@end


■TextureCallback.m

#import "TextureCallback.h"

@implementation TextureCallback

+ (id)callbackWithBlock:(textureCallbackBlock_t)block
{
return [[[self alloc] initWithBlock:block] autorelease];
}

- (id)initWithBlock:(textureCallbackBlock_t)block
{
if ((self=[super init])) {

/*
* 「5-2-4 Block_copy」(188ページ)
* 渡されたBlockをretainするためにObjective-Cのcopyを使用。
*/
block_ = [block copy];
}

return self;
}

- (void)dealloc
{

/*
* 「5-2-4 Block_copy」(188ページ)
* retainしたBlockをreleaseするためにObjective-Cのreleaseを使用。
*/
[block_ release];
[super dealloc];
}

- (void)callback:(CCTexture2D *)texture
{
/*
* 「5-2-2 値としてのBlock」(184ページ)
* cocos2dのイメージ非同期読み込み終了時Blockを実行。
*/
block_(texture);
}

@end


て感じで。使うときは


#import "TextureCallback.h"

/*
* 非同期イメージ読み込み終了時に
* 実行されるBlockを指定。
*/
TextureCallback *textureCallback =
[TextureCallback callbackWithBlock:
^(CCTexture2D *texture) {

[self addTexture:texture index:index];

}];

/*
* cocos2dの非同期イメージ読み込み
* (要メインスレッド(Main Queue))
*/
[[CCTextureCache sharedTextureCache]
addImageAsync:path target:textureCallback
selector:@selector(callback:)];



さらに、


+ (id)addImageAsyncWithBlock:(NSString *)path block:(textureCallbackBlock_t)block
{
id textureCallback = [[[self alloc] initWithBlock:block] autorelease];

[[CCTextureCache sharedTextureCache]
addImageAsync:path target:textureCallback
selector:@selector(callback:)];

return textureCallback;
}


こんな感じのクラスメソッドにすれば、


#import "TextureCallback.h"

/*
* 非同期イメージ読み込み終了時に
* 実行されるBlockを指定。
*/
[TextureCallback addImageAsyncWithBlock:path block:^(CCTexture2D *texture) {

[self addTexture:texture index:index];

}];


あらすっきり。


CCTextureCacheは渡ってきたtextureCallbackをコールバック終了までretainするので、コールバック終了までちゃんと生存。textureCallbackで持つことになるblockもtextureCallback生存中はretain(copy)されるので、メモリ管理も簡単、安心。


iOS 4プログラミングブックのサンプルコードは、http://www.impressjapan.jp/books/2976のダウンロードよりどうぞー