【问题标题】:performSelector:withObject:afterDelay: not making callperformSelector:withObject:afterDelay: 不打电话
【发布时间】:2012-01-05 16:49:29
【问题描述】:

在一个方法中,我想在 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];

这里,showActionSheet 在 drawMap 完成 6 秒后被调用。我猜我还不明白的线程正在发生一些事情......

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

【问题讨论】:

  • 你能把showActionSheet方法的代码贴出来吗?

标签: iphone objective-c ios


【解决方案1】:

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

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

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

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

【讨论】:

  • 是的,我最近更新了 MBProgressHUD 库,在他们的操作方法中,他们建议获取主线程并像这样运行方法。我也改用这种方式了。
  • OP 需要主线程来显示操作表。我的问题有点不同,但这基本上仍然是一个很好的解决方案。我使用 dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{ 而不是在主队列上运行。
【解决方案2】:

尝试使用:

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

【讨论】:

  • 这确实有效,该方法被调用但没有延迟,这是我想要做的。我希望 showActionSheet 在 drawMap 完成后等待 n 秒(我正在更改视图并希望用户在操作表出现之前看到更改)。
  • 是的。主线程方法没有延迟,你可以试试上面编辑的部分
  • 哈哈,效果很好!认为您可以解释为什么会这样吗?我猜它与线程有关,这是将进程返回到确实被杀死的主线程?
  • showWhileExecuting 在新线程上工作,因此在调用任何其他选择器之前,您需要从那里移至主线程。这是主要逻辑。欲了解更多信息,您可以查看 - developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
  • 太棒了,感谢您提供的信息。我添加了一些 NSLog(@"%@", [NSThread currentThread]) 和 ya,只要它进入 -(void) 就选择它的一个新线程。修复后,当它回到主线程时 -(void)showActionSheet。
【解决方案3】:

你的班级还存在于内存中吗?

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

你提到了线程。如果您的 performSelector 不是从 MainThread 调用的,则可能会导致问题(UI 的事情应该在主线程上完成)。

【讨论】:

  • 不,课程不会消失。我只是很困惑为什么 [self showActionSheet] 有效,而 performSelector 无效。
【解决方案4】:

当我在 ReactiveCocoa 创建的后台线程中调用 performSelector:withObject:afterDelay: 时遇到了同样的问题。 如果我以 ReactiveCocoa 的方式执行该块,该块将被正确调用:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多