PerformSelector: withObject: afterDelay: не делать вызов - программирование
Подтвердить что ты не робот

PerformSelector: withObject: afterDelay: не делать вызов

в методе, я хочу вызвать метод через n секунд:

    self.toolBarState = [NSNumber numberWithInt:1];
    [self changeButtonNames];
    [self drawMap];
    [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2];

Я хочу показать панель действий через 2 секунды после завершения рисования. когда я использую этот performSelector, он никогда не делает вызов.

если я просто поставлю [self showActionSheet];, он работает отлично. есть ли причина, по которой функция Performer не выполняет вызов?

EDIT: в другой части моего кода я делаю тот же вызов, и он работает:

HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = (id) self;
[HUD showWhileExecuting:@selector(drawMap) onTarget:self withObject:nil animated:YES];

[self performSelector:@selector(showActionSheet) withObject:nil afterDelay:6];

здесь, showActionSheet получает вызов через 6 секунд после завершения drawMap. Я предполагаю, что что-то происходит с потоками, которые я еще не понимаю...

EDIT2:

-(void)showActionSheet
{
    InspectAppDelegate *dataCenter = (InspectAppDelegate *) [[UIApplication sharedApplication] delegate];

    if (dataCenter.fieldIDToPass == nil)
    {
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selected Boundary Options" delegate:(id) self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Analyze a Field",@"Retrieve Saved Analysi", @"Geotag Photos", @"Refresh the map",nil];
        actionSheet.tag = 0;
        [actionSheet showInView:self.view];
    }
    else
    {
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selected Boundary Options" delegate:(id) self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Analyze a Field",@"Retrieve Saved Analysi", @"Geotag Photos", @"Attribute the Field", @"Refresh the map",nil];
        actionSheet.tag = 0;
        [actionSheet showInView:self.view];

    }
}

EDIT3:

ok, поэтому ход вызовов методов:

-(void) foundDoubleTap:(UITapGestureRecognizer *) recognizer
{        
    [HUD showWhileExecuting:@selector(select) onTarget:self withObject:nil animated:YES];
}

-(void) select
{   
        [self changeButtonNames];
        [self drawMap];
        [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2];
}

showActionSheet никогда не вызывается. как я уже сказал, я уверен, что это проблема с потоками. если вызывать его с помощью [self showActionSheet], он будет работать. =/

4b9b3361

Ответ 1

Попробуйте использовать:

-(void) select {   
    [self changeButtonNames];
    [self drawMap];
    [self performSelectorOnMainThread:@selector(showActionSheet) withObject:nil waitUntilDone:YES];
}

-performSelector:withObject:afterDelay: планирует таймер в том же потоке для вызова селектора после прошедшей задержки.

Может быть, это будет работать для вас:

-(void) select {   
    [self changeButtonNames];
    [self drawMap];
    [self performSelectorOnMainThread:@selector(someA) withObject:nil waitUntilDone:YES];
}

-(void)someA {
    [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2];
}

Ответ 2

Я столкнулся с этой же проблемой, и по необходимости я решил ее немного отличаться от принятого ответа. Заметьте, я хотел, чтобы мои задержки и селекторы были переменными? Использование блока позволяет мне оставаться в моем текущем методе.

dispatch_async(dispatch_get_main_queue(), ^{
       [self performSelector:loopSelector withObject:nil afterDelay:cycleTime];
});  

Кстати, это определенно проблема с потоками. Документация для performSelector: withObject: afterDelay: заявляет, что это будет выполняться в текущем потоке после задержки, но иногда этот цикл запуска потока больше не активен.

Более подробное обсуждение этого вопроса можно найти здесь

Ответ 3

Сохраняется ли ваш класс в памяти?

Если ваш класс уходит до срабатывания функцииSelector, вы завершаете отправку сообщения на nil (что не вызовет ничего). Вы можете проверить это, сбросив NSLog в свой dealloc()

Вы упомянули темы. Если ваш PerformSelector не вызывается из MainThread, это может вызвать проблемы (вещи пользовательского интерфейса должны выполняться в основном потоке).

Ответ 4

У меня такая же проблема, когда я вызываю performSelector:withObject:afterDelay: в фоновом потоке, созданном ReactiveCocoa. Если я выполнил блок в пути ReactiveCocoa, блок будет вызван правильно:

 [[[RACSignal empty] delay:2.0] subscribeCompleted:^(){
    // do something
 }];

Я думаю, что есть какая-то магия в модели Threading ReactCocoa.