performSelector:withObject:afterDelay:不进行调用

时间:2012-01-05 16:49:30

标签: iphone objective-c ios

在一个方法中,我想在n秒后调用一个方法:

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

我想在drawMap完成后2秒显示操作表。当我使用这个performSelector时,它永远不会打电话。

如果我只是把[self showActionSheet];,它的工作正常。是否有理由为什么performSelector没有进行调用?

编辑:在我的代码的另一部分,我做同样的电话,它的工作原理:

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

这里,showMap完成后6秒就会调用showActionSheet。我猜测还有一些我不理解的线程......

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]调用它,它将运行。 = /

4 个答案:

答案 0 :(得分:36)

我遇到了同样的问题,我必须解决它与接受的答案略有不同。注意我希望我的延迟和选择器是变量?使用块可以让我保持在当前的方法中。

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

顺便说一句,这绝对是一个线程问题。 performSelector的文档:withObject:afterDelay:声明这将在延迟后在当前线程上执行,但有时该线程的运行循环不再有效。

可以找到关于该主题的更详细讨论here

答案 1 :(得分:20)

尝试使用 -

  -(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 :(得分:1)

你的班级是否仍然存在于记忆中?

如果您的课程在performSelector触发之前消失,您是否最终将消息发送到nil(这不会导致任何事情发生)。 您可以通过将NSLog放入dealloc()

进行测试

你提到了线程。如果没有从MainThread调用你的performSelector,它可能会导致问题(UI应该在主线程上完成)。

答案 3 :(得分:0)

当我在ReactiveCocoa创建的后台线程中调用 [[[RACSignal empty] delay:2.0] subscribeCompleted:^(){ // do something }]; 时遇到了同样的问题。 如果我以ReactiveCocoa的方式执行块,则将正确调用该块:

DATETIME

我想ReactiveCocoa的线程模型中有一些魔力。