динамическое приведение типа target-c, в то время как touchesBegan выбирает узел

У меня есть пара узлов спрайтов на моем экране: child1, child2, которые наследуются от родителя. У родителя есть метод customAction, который перезаписывает дочерние1 и дочерние2. И все они наследуются от skspritenode.

Теперь, в моем touchesBegin я использую линию

SKSpriteNode * touchedNode = (SKSpriteNode *)[self nodeAtPoint:positionInScene];

Но я хочу вызвать дочернюю версию customAction из дочерней1, если затронутый узел имеет тип дочерняя1 и дочерняя2 версия, если дочерняя2.

Есть ли «красивый» или «лучший» способ сделать это, кроме как пометить спрайты, а затем использовать оператор switch для приведения узла к соответствующему дочернему типу?

Спасибо!

редактировать: код

// parent class
@interface animal : SKSpriteNode

-(int)getID;
-(void)yell;

@end

@implementation Animal
{
    int animalID;

    bool clickable;
}

-(id)initAnimalWithIDWithImage:(int)ID :(NSString *)animalType
{
    NSDictionary * returnedAnimal = [animalParser getAnimalByType:animalType];
    NSString *Icon  = [returnedAnimal objectForKey:@"Icon"];

    self = [super initWithImageNamed:Icon];

    animalID = ID;

    return self;
}

-(int)getID
{
    return animalID;
}

-(void)yell
{
    // **todo**
}

@end

// child1
@interface bear : animal

-(void)yell;

@end

@implementation bear

-(id)initBearWithID:(int)ID
{
    return [super initAnimalWithIDWithImage:ID :@"Bear"];
}

-(void)yell
{
    // **todo**
}

@end

// child2
@interface boar: animal

-(void)yell;

@end

// identical to bear

// in the scene

-(id)initGameScene:(CGSize)size :(int)mode
{
    [self initialize:size];
    if(self = [super initWithSize:size])
    {
        bear testBear = [[Bear alloc] initBearWithID:idCount++];
        testBear.position = CGPointMake(300,300);

        [self addChild:testBear];
    }
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch * touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    // problem solved!
    // this is wrong
    // SKSpriteNode * touchedNode = (SKSpriteNode *)[self nodeAtPoint:positionInScene];

    // this is right
    animal *touchedNode = (animal *)[self nodeAtPoint:positionInScene];

    [touchedNode yell]; 

    // need to something like if touchedNode is a bear do bear yell.. if boar do boar yell
}

person learning__2__code    schedule 20.09.2014    source источник
comment
Посмотрите на утиную печать. В Objective-C это есть.   -  person Hot Licks    schedule 21.09.2014


Ответы (1)


Учитывая код, который вы разместили, [touchedNode yell]; — это все, что вам нужно. Об остальном позаботится динамическая отправка сообщений. Если возможно, что ваш узел не реализует yell, сначала проверьте respondsToSelector:.

Чтобы ответить на вопрос, как явно идентифицировать тип, вы можете использовать isKindOfClass. То есть if ([touchedNode isKindOfClass:[bear class]]).

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/isKindOfClass:

Кроме того, называйте свои классы заглавными буквами. Многие вещи в вашем приложении будут работать лучше, если вы будете следовать соглашениям, таким как регулярное присвоение имен классам и методам доступа.

person StilesCrisis    schedule 20.09.2014
comment
Но когда я это делаю, он возвращает SKSpriteNode, мне нужно, чтобы он возвращал child1 (или child2)! - person learning__2__code; 20.09.2014
comment
О, я думал, что дети из разных классов. На самом деле, есть ли что-то, что мешает вам сделать так, чтобы child1 и child2 наследовали от SKSpriteNode и становились разными подклассами? - person StilesCrisis; 20.09.2014
comment
Извините, я не уверен, правильно ли я объясняю себя. Child1 и child2 наследуются от родителя, который наследуется от skspritenode. проблема в том, что SKSpriteNode * touchedNode = (SKSpriteNode *)[self nodeAtPoint:positionInScene]; touchedNode имеет тип skspritenode, поэтому ismemberof возвращает skspritenode. И у цели c нет «var», как у C#, поэтому я не уверен, как найти класс - person learning__2__code; 20.09.2014
comment
Пожалуйста, покажите ваш фактический код и иерархию наследования. Я не понимаю тебя. - person StilesCrisis; 20.09.2014
comment
Эй, я добавил код, извините, я был медленным, первый раз публикую здесь! - person learning__2__code; 20.09.2014
comment
Вау, я не понял, что вы сделали редактирование для обновления. Но я получаю сообщение об ошибке No visible @interface for SKSpriteNode объявляет селектор «yell». - person learning__2__code; 21.09.2014
comment
Я опустил не относящиеся к делу методы, но в остальном да. - person learning__2__code; 21.09.2014
comment
Вам нужно будет опубликовать больше кода для дальнейшей отладки. - person StilesCrisis; 21.09.2014
comment
Ах, я понял, нужно привести touchedNode к животному в этой строке. не могу оставить его на skspritenode. Большое вам спасибо за ваше время. - person learning__2__code; 21.09.2014