【问题标题】:Does didFinishPickingMediaWithInfo get called in background thread?didFinishPickingMediaWithInfo 是否在后台线程中被调用?
【发布时间】:2017-09-28 10:07:10
【问题描述】:

我认为UIImagePickerController 委托方法(或任何UIKit 委托方法)在主线程中被调用。但是在这里,当从画廊或相机中选择图像时,didFinishPickingMediaWithInfo 方法似乎没有被调用,UIKit 委托方法必须在主线程上调用,对吧?显式调度到主线程有效。 Apple 文档中也没有提及这一点。

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString* ,id> *)info{

    uploadImage = info[UIImagePickerControllerOriginalImage]; // Set selected image            
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.leftButton setImage:[UIImage imageNamed:@"image_attach.png"]
                         forState:UIControlStateNormal];
    });

    // The following does not work.
    //[self.leftButton setImage:[UIImage imageNamed:@"image_attach.png"]
                     //forState:UIControlStateNormal];  
}

底线,所有 UIKit 委托方法都在主线程上调用吗?或者有些在非主线程中被调用?为什么我们认为没有必要将我们的代码分派到主线程,但最终这样做会使事情发生这种不一致?如果有人知道答案,请澄清。

编辑: 正如 Rob 所建议的,我检查了这个方法 [NSThread isMainThread] 以查看代码在哪个线程中执行。它清楚地返回true 以确认我在主线程中,但奇怪的是没有将我的setImage 方法显式分派到主队列,代码不起作用。另外,我尝试将我的代码移动到选择器的 dismiss 方法的完成处理程序,瞧,它可以在没有显式主线程块的情况下工作!

仍然对为什么会有这样的行为感到困惑......

【问题讨论】:

  • 很高兴在这里见到你,我不确定问题阅读文档:developer.apple.com/documentation/uikit#//apple_ref/doc/uid/…
  • @karthikeyan 也很高兴见到你。是的,我知道这一点。但我想具体了解 UIKit 委托方法是在主线程还是后台线程中调用。
  • 根据文档 UIKit 类仅来自您应用的主线程或主调度队列
  • @karthikeyan 它只在主线程中被调用。但不知何故,该代码仅适用于dispatch_async 块。
  • 顺便问一下,你为什么要在 imagepicker 委托中设置按钮图像

标签: ios uikit uiimagepickercontroller grand-central-dispatch ios-multithreading


【解决方案1】:

当我测试它时,它是在主线程上调用的。我建议检查 [NSThread isMainThread] 以确认(或者,在 Swift 中,dispatchPrecondition(condition: .onQueue(.main))Thread.isMainThread)。在我的测试中,它在主线程上。

如果它不是主线程(!),我会检查你在哪里展示它,以确保你从主线程展示它。

我想不出在后台线程上调用的任何与 UI 相关的委托方法。对于非 UI 委托方法,有很多不使用主线程,但是像这样以 UI 为中心的 API 使用主线程。

【讨论】:

  • 我检查了[NSThread isMainThread],它返回YES。但是,如果没有将我的 setImage 方法显式分派到主队列,它就不起作用。奇怪....
  • 您的按钮在导航控制器上吗?如果是这样,也许选择器的导航控制器会干扰它,并且调度异步将其推迟足够长的时间以实现您想要的效果。这是推迟某些 UI 更新的老套路。
  • 是的,该按钮位于导航控制器内,我正在展示来自UIAlertAction 处理程序块的选择器。这会是个问题吗?我想这不应该,因为isMainThread 无论如何都会返回true
  • np。因此,我不知道为什么 setImage 仅在延迟到 dispatch_async 时才有效。但是我仍然倾向于将setImage 放在选择器的dismiss 的完成处理程序中,或者使用按钮放在视图控制器的viewDidAppear 中。
  • 就像我说的,我不知道为什么setImage 只在延迟时有效。这是非常不寻常的。我怀疑松弛文本视图控制器在其自己的外观方法中正在做的事情(例如重置按钮)或类似的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2016-04-17
相关资源
最近更新 更多