楽天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のダウンロードよりどうぞー