2

I thought that the UIImagePickerController delegate methods (or any UIKit delegate method) get called in the main thread. But here, when picking image from gallery or camera, the didFinishPickingMediaWithInfo method does not seem to get called in one, and UIKit delegate methods must be called on main thread right? Dispatching explicitly to main thread works. There are no mentions about this in the Apple documentation as well.

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

Bottom line, do all UIKit delegate methods get called on main thread? Or some get called in non-main thread? Why this inconsistency where we BELIEVE that there is no necessity to dispatch our code to main thread, but in the end doing that makes things work? If someone knows the answer please clarify.

EDIT: As suggested by Rob, I checked with this method [NSThread isMainThread] to see in which thread the code gets executed. It clearly returned true to confirm that I am in the main thread, but strangely without dispatching my setImage method to main queue explicitly, the code does not work. Also, I tried moving my code to the picker's dismiss method's completion handler, voila it works without an explicit main thread block!

Still confused on why this is behaving like this...

badhanganesh
  • 3,427
  • 3
  • 18
  • 39

1 Answers1

2

When I tested it, it was called on the main thread. I'd suggest checking [NSThread isMainThread] to confirm (or, in Swift, dispatchPrecondition(condition: .onQueue(.main)) or Thread.isMainThread). In my test, it was on the main thread.

If it's not the main thread (!), I'd check where you present it, to make sure you presented it from the main thread.

I can't think of any UI-related delegate methods that are called on a background thread. For non UI delegate methods, there are plenty that don't use the main thread, but UI-centric API like this use the main thread.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I checked with `[NSThread isMainThread]` and it returns `YES`. However without explicitly dispatching my `setImage` method to main queue, it does not work. Strange.... – badhanganesh Sep 28 '17 at 11:16
  • is your button on a navigation controller? if so, perhaps the picker's navigation controller is interfering with that and the dispatch async is deferring it long enough to accomplish you're desired effect. It's an old, kludgy trick for deferring some UI update. – Rob Sep 28 '17 at 11:22
  • Yes, the button is inside a navigation controller, and I am presenting the picker from `UIAlertAction` handler block. Can that be a problem? I guess that shouldn't be, because the `isMainThread` returns `true` anyway. – badhanganesh Sep 28 '17 at 11:28
  • I thought you asked the presence of button inside a navigation controller. The button is not present in the navigation bar. I misread your question. The button is actually the left button of the `slackTextViewController`. – badhanganesh Sep 28 '17 at 11:38
  • 1
    np. I therefore have no idea why `setImage` only works when deferred in a `dispatch_async`. But I'd still be inclined to put the `setImage` inside the completion handler of the `dismiss` of the picker or in the `viewDidAppear` of the view controller with the button. – Rob Sep 28 '17 at 11:45
  • It works without `dispatch_async` in the completion handler of the `dismiss`. Why is that happening? I have no idea. And thanks for the nifty method `isMainThread`. – badhanganesh Sep 28 '17 at 11:53
  • 1
    Like I said, I don't know why `setImage` only works when deferred. That's very unusual. I'd suspect either something that the slack text view controller is doing in its own appearance methods (e.g. resetting buttons) or something like that. – Rob Sep 28 '17 at 11:57