2

我正在创建一个自定义模式层。这个想法是用户看到一个城市,点击该城市并接受或拒绝该位置。

NSMethodSignature用来处理回调,所以我知道用户是点击了模态层中的Tick(接受)还是Cross(拒绝)按钮。

但是,由于某种原因,应用程序在调用回调后会崩溃,并在从模式返回时给我一个错误的访问错误。

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方法时发生错误访问错误。

它输出日志很好,但是当它碰到城市对象时它会崩溃。我不知道为什么会发生这种情况,它不应该为空或导致任何形式错误。

好的,所以模态层有点复杂,但为了这个问题,我把它删掉了:

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

我已将问题跟踪到调用回调的时间,但是我不明白为什么它会崩溃或给我错误。它应该仍然在内存中有城市对象吗?

这可能是什么原因造成的?

4

1 回答 1

0

我现在已经做到了。这是自动释放。我已经删除了

为了防止在模态下单击,或者有人非常快速地多次按下按钮,我CoverLayer在我的 ModalLayer.m 文件中放置了一个

// class that implements a black colored layer that will cover the whole screen 
// and eats all touches except within the dialog box child
@interface CoverLayer : CCLayerColor {
}

@end
@implementation CoverLayer
- (id)init {
    self = [super init];
    if (self) {        
        [self initWithColor:ccc4(0,0,0,0) 
                      width:[CCDirector sharedDirector].winSize.width 
                     height:[CCDirector sharedDirector].winSize.height];
        self.isTouchEnabled = YES;
    }
    return self;
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchLocation = [self convertTouchToNodeSpace: touch];
    CCNode *dialogBox = [self getChildByTag: kDialogTag];

    // eat all touches outside of dialog box
    return !CGRectContainsPoint(dialogBox.boundingBox, touchLocation);
}

- (void) registerWithTouchDispatcher {
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}

@end

然后我可以使用我的ModalLayer实现来初始化它,然后用一个小动画关闭模式,即,

-(void) onButtonPressed:(id) sender
{
    NSInteger buttonIndex = [sender tag];
    [callback setArgument:&buttonIndex atIndex:2];
    [callback invoke];

    id fadeOut    = [CCFadeTo actionWithDuration:0.2f opacity:0];
    id remove = [CCCallFuncND actionWithTarget:self selector:@selector(removeFromParentAndCleanup:) data:(void*)NO];        


    [self.coverLayer runAction:
     [CCSequence actions:
      fadeOut, remove,
      nil]];
}

无论如何,我相信我解决了这个问题,因为它似乎与自动释放有关

于 2012-04-20T02:19:20.243 回答