Как заставить executeSelector работать с NSInvocation? - PullRequest
0 голосов
/ 13 февраля 2011

Мне нужно передать прикосновения и событие от touchesBegan моему собственному методу, вызываемому executeSelector. Я использую NSInvocation для упаковки аргументов, но у меня проблемы с целью.

Причина, по которой я это делаю, заключается в том, что я могу обрабатывать другие события прокрутки.

Вот мой код:

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event
{           
    UITouch *theTouch = [touches anyObject];

    switch ([theTouch tapCount]) 
    {
        case 1:
            NSInvocation *inv = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector:@selector(handleTap: withEvent:)]];
            [inv setArgument:&touches atIndex:2];
            [inv setArgument:&event atIndex:3];
            [inv performSelector:@selector(invokeWithTarget:) withObject:[self target] afterDelay:.5];
            break;
    }
}

Где handleTap определяется как:

-(IBAction)handleTap:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesBegan:touches withEvent:event];
}

Моя проблема в том, что при компиляции я получаю предупреждение:

'CategoryButton' многие не отвечают на '-target'

и когда я запускаю его, он падает с:

- [Цель CategoryButton]: нераспознанный селектор отправлен в экземпляр 0x5b39280

Должен признать, что я не совсем понимаю, что цель пытается здесь сделать и как она установлена.

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 13 февраля 2011

Я думаю, вам нужно потратить некоторое время, чтобы внимательно прочитать код, построчно.

[inv performSelector:@selector(invokeWithTarget:) withObject:[self target] afterDelay:.5];

Это не делает то, что вы думаете.Через полсекунды после выполнения этого метода это произойдет:

[inv invokeWithTarget:[self target]];

Во-первых, у вашего класса CategoryButton нет метода с именем target.Во-вторых, почему задержка?Если вы используете эти прикосновения для прокрутки, задержка в 0,5 секунды будет чрезвычайно болезненной для пользователей.

Почему вы вообще используете класс NSInvocation?Если вам действительно нужна задержка, вы можете просто использовать метод performSelector: в своем экземпляре CategoryButton:

NSArray *params = [NSArray arrayWithObjects:touches, event, nil];
[self performSelector:@selector(handleTap:) withObject:params afterDelay:0.5];

Обратите внимание, что методы performSelector: поддерживают только один аргумент, поэтому вам нужно обернуть их вNSArray.(В качестве альтернативы вы можете использовать NSDictionary.)

Вы должны будете обновить свой метод handleTap:, чтобы он принимал NSArray / NSDictionary и, если необходимо, выявлял аргументы.

Но, опять же, еслине нужно откладывать, почему бы просто не вызвать метод самостоятельно:

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event
{           
    UITouch *theTouch = [touches anyObject];

    switch ([theTouch tapCount]) 
    {
        case 1:
            [super touchesBegan:touches withEvent:event];
        break;
    }
}

Возможно, я неправильно понимаю ваши намерения, но, похоже, вы делаете этот путь более сложным, чем нужно.

0 голосов
/ 13 февраля 2011

Должен признать, что я не совсем понимаю, что цель пытается сделать здесь и как она установлена.

Цель - это объект, для которого вы хотите выполнить вызов. Вы получаете сбой, потому что выбранный вами объект - [self] - не отвечает на сообщение target. Я думаю, вы, возможно, немного запутались из-за того, что вам нужно передать.

С вашим текущим кодом вы просите, чтобы ваш вызов был выполнен для свойства target self. Вы, вероятно, не хотите этого делать - я предполагаю, что вы хотите, чтобы ваш вызов выполнялся просто на self. В этом случае используйте это:

[inv performSelector:@selector(invokeWithTarget:) withObject:self afterDelay:.5];
...