从块返回导航

Rob*_*ner 4 multithreading uinavigationcontroller ios

我有我认为在后台线程上发生的UX操作.在使用块的方法中,我正在调用的成功:

[self.navigationController popViewControllerAnimated:TRUE]; 
Run Code Online (Sandbox Code Playgroud)

我正在崩溃,所以我认为检查当前线程并调用performSelectorOnMainThread可能会解决这个问题,但我不知道如何设置调用的@selector部分.

[self performSelectorOnMainThread:@selector([self.navigationController popViewControllerAnimated:TRUE]) withObject:nil waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)

不管用.什么是正确的语法?

Lyn*_*ott 56

要强制方法在主线程上执行,您可以使用:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.navigationController popViewControllerAnimated:TRUE]; 
});
Run Code Online (Sandbox Code Playgroud)

  • 呃,这对我来说是一个折腾... [[NSOperationQueue mainQueue] addOperationWithBlock更通用,因为它支持更多的功能,如停止/启动,依赖等.但是低级语言dispatch_async(dispatch_get_main_queue()(即GCD)有点更快.猜猜这取决于你需要什么...但是因为popViewControllerAnimated:在这种情况下是如此快速的操作,也许它不需要更高级[[NSOperationQueue mainQueue] addOperationWithBlock的所有花里胡哨...... (16认同)
  • 你的代码是正确的,但风格方面我更喜欢更高级别:[[NSOperationQueue mainQueue] addOperationWithBlock:^ {[self.navigationController popViewControllerAnimated:TRUE];}]; (5认同)
  • 对我来说,它不是关于额外的功能,而是关于哪个更具可读性.而速度只有在测试代码并发现它很慢时才很重要.我发现Objective-C比直接C更具可读性,Objective-C界面中的'mainQueue'跳出比C中的dispatch_get_main_queue()跳出更多.如果你相信Objective-C,你会留在Objective-C什么时候可以. (5认同)

hso*_*soi 6

严格来说,由于工作方式的限制,你无法直接做你想做的事-performSelectorOnMainThread:.但是,在任何类self中,您都可以定义这样的方法:

- (void)doPop {
  [self.navigationController popViewControllerAnimated:YES];
}
Run Code Online (Sandbox Code Playgroud)

然后

[self performSelectorOnMainThread:@selector(doPop)];
Run Code Online (Sandbox Code Playgroud)

详细说明为什么语法不起作用:

选择器传递给-performSelectorOnMainThread:必须是一个不带参数的选择器,或者某种类型的单个参数id.虽然-popViewControllerAnimated:是一个采用单个参数的选择器,但该参数是类型的BOOL(顺便使用YESNO不是TRUEFALSE).

同样,@selector将只是方法的名称,而不是您希望在其上调用它的对象(在本例中self.navigationController).

从消息传递对象的角度考虑它.您希望self.navigationController对象-popViewControllerAnimated:在主线程上执行选择器,因此您将以这种方式构造消息传递:

[self.navigationController performSelectorOnMainThread:@selector(popViewControllerAnimated:) withObject:nil waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)

但问题又出现了必要的论点.所以既然你不能pop以这种方式直接调用,那就是我的上述建议.它允许您perform根据其语义进行调用,然后仍然可以pop使用其语义正确调用.