カスタムモーダルレイヤーを作成しています。アイデアは、ユーザーが都市を見て、その都市をクリックし、その場所を受け入れるか拒否するというものです。
私NSMethodSignature
はコールバックを処理するために使用していたので、ユーザーがモーダル レイヤーのTick
(Accept) ボタンまたはCross
(Reject) ボタンをクリックしたかどうかがわかります。
ただし、何らかの理由でコールバックを呼び出すとアプリがクラッシュし、モーダルから戻るときに不正なアクセス エラーが発生します。
0x000d584e <+0174> mov %eax,0x4(%esp)
0x000d5852 <+0178> call 0xd6006 <dyld_stub_objc_msgSend>
0x000d5857 <+0183> mov -0x8(%ebp),%eax Thread 1: Program received signal: EXC_BAD_ACCESS
クラスで都市オブジェクトが定義されているため、なぜこれが起こっているのかわかりません。
たとえば、私の .h ファイルには次のものがあります。
@interface MapMenuLayer : CCLayer
{
CCArray *listOfCities;
City *city;
}
@property (nonatomic, retain) CCArray *listOfCities;
@property (nonatomic, retain) City *city;
そして、私の .m ファイルには次のものがあります。
@synthesize listOfCities, city;
後で、ページ上の各都市の表示をクリック可能なCCMenu
アイテムとして定義します。ユーザーが都市をクリックすると、次のように呼び出されます。
-(void) onMenuItem:(id)sender
{
NSLog(@"sender = %d", [sender tag]);
self.city = [self.listOfCities objectAtIndex:[sender tag]];
NSString *cityName = self.city.name;
NSLog(@"cityName = %@", cityName);
// Launch the modal layer
CityModalLayer *cityModalLayer = [[[CityModalLayer alloc] initWithCity:self.city target:self selector:@selector(onDialogButton:)] autorelease];
[cityModalLayer show:self];
}
// This is called when the modal is closed or actioned upon
- (void) onDialogButton:(NSInteger)buttonIndex
{
NSLog(@"onDialogButton:buttonIndex: %d", buttonIndex);
NSString *cityName = self.city.name;
NSLog(@"You selected: cityName = %@", cityName);
}
アプリケーション フローがモーダル レイヤーから戻り、onDialogButton
メソッドが実行されると、不正なアクセス エラーが発生します。
ログは問題なく出力されますが、都市オブジェクトに当たるとクラッシュします。なぜこれが起こっているのかわかりません.nullにしたり、正式なエラーを引き起こしたりするべきではありません.
さて、モーダルレイヤーは少し複雑ですが、この質問のために切り詰めました:
-(id) initWithCity:(City *)cityObj target:(id)target selector:(SEL)selector
{
if((self=[super init]))
{
[self initWithColor:ccc4(0, 0, 0, 255)];
[self setOpacity:80];
[self setIsTouchEnabled:YES];
self.city = cityObj;
// Setup the signature class
NSMethodSignature *sig = [[target class] instanceMethodSignatureForSelector:selector];
callback = [NSInvocation invocationWithMethodSignature:sig];
[callback setTarget:target];
[callback setSelector:selector];
[callback retain];
// -----
// MENU
// The frames are not in this code, but they do exist
// Add modal menu
// Modal Menu (Tick/Cross)
CCMenu *modalMenu = [CCMenu menuWithItems:nil];
CCSprite *closeButtonOff = [CCSprite spriteWithSpriteFrameName:@"closeButton_Off.png"];
CCSprite *closeButtonOn = [CCSprite spriteWithSpriteFrameName:@"closeButton_On.png"];
CCSprite *tickButtonOff = [CCSprite spriteWithSpriteFrameName:@"tickButton_Off.png"];
CCSprite *tickButtonOn = [CCSprite spriteWithSpriteFrameName:@"tickButton_On.png"];
// Tick button
CCMenuItemSprite *tickBtnItem = [CCMenuItemSprite itemFromNormalSprite:tickButtonOff selectedSprite:tickButtonOn target:self selector:@selector(onButtonPressed:)];
[tickBtnItem setTag:1];
[tickBtnItem setPosition:CGPointMake(130, -95)];
[tickBtnItem setIsEnabled:YES];
// Close button
CCMenuItemSprite *closeBtnItem = [CCMenuItemSprite itemFromNormalSprite:closeButtonOff selectedSprite:closeButtonOn target:self selector:@selector(onButtonPressed:)];
[closeBtnItem setTag:0];
[closeBtnItem setPosition:CGPointMake(-130, -95)];
[closeBtnItem setIsEnabled:YES];
// Add stuff to modal
[modalMenu addChild:closeBtnItem];
[modalMenu addChild:tickBtnItem];
// Add menu to the modalFrame
[modalFrame addChild:modalMenu z:2];
// --
// Add modalFrame to modalLayer
[self addChild:modalFrame];
} // end if
return self;
}
// This invokes the action
-(void) onButtonPressed:(id) sender
{
NSInteger buttonIndex = [sender tag];
NSLog(@"onButtonPressed: %d", buttonIndex);
[callback setArgument:&buttonIndex atIndex:1];
[callback invoke];
[self removeFromParentAndCleanup:YES];
}
-(void) dealloc
{
[callback release];
[super dealloc];
}
コールバックが呼び出されるまで問題を追跡しましたが、クラッシュしたり、エラーが発生したりする理由がわかりません。それはまだ都市オブジェクトをメモリに持っているべきですか?
何が原因でしょうか?