「プログラムはシグナルを受信しました:“0”。 データフォーマッタが一時的に使用できなくなっています。」と表示されるときの対処法

僕も一時期はまったのですが、cocos2dでiPhoneアプリ作っているときに、

プログラムはシグナルを受信しました:“0”。 データフォーマッタが一時的に使用できなくなっています。“続ける”の後で再試行します。(Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")

と表示され、アプリが強制終了する事象が起こってしまい、結構はまりました。そんなときの対処法をメモ。


データフォーマッタがが一時的に使用できない

twtterで、iphone_dev_jp に聞いてみたところ、


とのことです。


デバックツールを使ったところ、無限ループではなさそうだったので、重い画像の多様が原因と判断。その後、いろいろ調べました。

CCSpriteは、CCTextureCacheで自動的にキャッシュされている。

CCSprite *sprite = [CCSprite spriteWithFile: @"sample.png"];

多くの方が使用されているであろうこのメソッドを、「定義へジャンプ」で追っていくと、

-(id) initWithFile:(NSString*)filename
{
	NSAssert(filename!=nil, @"Invalid filename for sprite");

	CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
	if( texture ) {
		CGRect rect = CGRectZero;
		rect.size = texture.contentSize;
		return [self initWithTexture:texture rect:rect];
	}

	[self release];
	return nil;
}

という感じになっており、

[[CCTextureCache sharedTextureCache] addImage: filename];

部分でキャッシュされています。

なので、重い画像を多様する場合、その画像すべてがキャッシュされてしまっているため、それをどこかのタイミングで削除してあげないと、メモリ不足が原因でアプリが落ちてしまいます。


cocos2dまとめ記事でご紹介した


cocos2d performance tips2(翻訳)の記事にも

・CCTextureCacheを使うこと
・CCTextureCacheは、全てのイメージをキャッシュする
・どこでもその画像を使ってないとしてもメモリには画像が残っている
・メモリから画像を消す必要がある

とあります。

テクスチャの数はなるべく少なく

同じく、


cocos2d performance tips2(翻訳)の記事より、

・可能な限り、テクスチャatlasを使うこと
・CCSpriteSheetの子供として、CCSpriteを使うこと
・CCLabelの代わりにCCLabelAtlasかCCBitmapFontAtlasを使うこと
・CCTMXTileMapかCCTileMapAtlasを使うこと
・Atlasによる管理は、処理を複雑にするが、処理速度は速い。
  →(画像を1枚にまとめることができる為。OpenGLESの描画命令回数を減らす事ができる為。
・Atlasには、グループ分けして画像を登録しておくこと

ということで、描画回数を少なくするためにも、一枚の画像に複数の画像をまとめておくことが、メモリを節約するには大切です!

TextureCacheを解放するとき

すべてのTextureCacheを解放する

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
	[[CCDirector sharedDirector] purgeCachedData];
	
	// 全てのテクスチャを消します。
	[[CCTextureCache sharedTextureCache] removeAllTextures];    // available in v0.7
}


長期間使用していないTextureCacheを解放する

[[CCTextureCache sharedTextureCache] removeUnusedTextures];


一度しか使用しないTextureのCacheを解放する

CCTexture2D *texture = [sprite texture];
[[CCTextureCache sharedTextureCache] removeTexture: texture]]; 


このように、Textureをアプリごとに適切に解放してあげれば、データフォーマッタがなんちゃらというエラーはでなくなりました。

メモリ節約のためにも、TextureAtlasの使い方などは今後さらに研究していかねば。

iPod Touchなど、メモリの低い端末では、よくこのエラーがでてしまうので気をつけましょう。