2012-01-05 3 views
16

в методе, я хочу, чтобы вызвать метод после п секунд:performSelector: withObject: afterDelay: не делает вызов

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

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

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

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:

нормально, так что прогресс вызовов метода является :

-(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], он будет работать. =/

+0

Можете ли вы опубликовать код метода showActionSheet? –

ответ

20

Попробуйте using-

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

Это работает, метод вызван, но нет задержки, что я пытаюсь сделать. Я хочу, чтобы showActionSheet подождал n секунд после завершения рисования (я делаю изменения в представлении и хочу, чтобы пользователь видел это изменение до того, как был поднят лист действий). – Padin215

+1

Да. Нет никакой задержки на методах основной нити, вы можете попробовать отредактированную часть выше – rishi

+0

ha, которая отлично работает! Думаете, вы могли бы объяснить, почему это работает? Я предполагаю, что это имеет какое-то отношение к потокам, где это возвращает процесс к основному потоку, который убивает? – Padin215

1

Разве ваш класс по-прежнему существует в памяти?

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

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

+1

нет, класс не уходит. Я просто смущен, почему [self showActionSheet] работает, а performSelector этого не делает. – Padin215

35

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

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

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

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

+1

Да, недавно я обновил библиотеку MBProgressHUD и в своем практическом плане предложил получить основной поток и запустить методы именно так. Я тоже переключился на это. – Padin215

+1

+1 Короткий, симпатичный и работает как шарм! :) – Groot

+1

OP нуждается в основном потоке, чтобы показать лист действий. Моя проблема была немного иной, но это было по-прежнему в основном хорошим решением. Я использовал 'dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{' вместо запуска в главной очереди. – jab

0

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

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

Я предполагаю, что есть какая-то магия в потоковой модели в ReactiveCocoa в.

Смежные вопросы