3

I have a strange problem, the completion block from presentViewController doesn't execute lately. This is the code called on button tap

    DebugViewController * x = [[DebugViewController alloc] init];
    x.view.backgroundColor = [UIColor redColor];
    [self presentViewController:x animated:YES completion:^{
        NSLog(@"Hello world %@" , self );
    }];

DebugViewController is this class, self is a UIViewController in a structure like this: JASidepanels ---> (center panel) UINavigationController ---> self

As expected, the exact same code works in any other project, but it isn't working in mine since a few weeks. I recently added JASidePanels and some other Pods.

Here is what know surely :

  • the modal is presented, viewWillAppear and viewDidAppear are called, it animates in, it works correctly
  • viewWillDisappear is called on presenting VC, dealloc isn't, so it is live.
  • Other blocks work.
  • It is on the main thread

Any idea how could I debug why the block doesn't execute for me ?

Edit: Wow, this is extremely strange. I debugged whole day and tried to delete code line-by-line. However it seems I found something really really interesting. If on any of my viewcontrollers there is a property named exactly currentAction (which is the case in one of my VCs), the completion blocks won't execute in the whole application ! Can someone please confirm ? Here is a gist GIST, change it to currentAction.

Templar
  • 1,694
  • 1
  • 14
  • 32
  • Does it log if you remove `self` from the log? Also, have you set a breakpoint in there or just relying on the log? – Fogmeister May 29 '14 at 10:26
  • Of course i tried with breakpoints. I tried with other instructions too, it simply doesn't enter the block... Also tried to put the block into a local variable, retain it to be sure it isn't dealloc-ed, but still nothing. – Templar May 29 '14 at 10:30

2 Answers2

1

If on any of my viewcontrollers there is a property named exactly currentAction, the completion blocks won't execute in the whole application ! Can someone please confirm ?

That's probably because UIViewController has an instance variable called _currentAction, as you can see in this part of UIViewController.h:

id               _dimmingView;
id               _dropShadowView;

id                _currentAction;
UIStoryboard     *_storyboard;

Declaring a property called currentAction and using the default synthesis for the accessors would interfere with that ivar. To avoid that, explicitly synthesize the accessors and provide a different name for the ivar to back your property. Try adding a line like this to your class:

@synthesize currentAction=_myCurrentAction;

That might help you avoid interfering with the existing ivar, as long as UIViewController only accesses _currentAction directly and doesn't use any internally-declared accessor or KVC.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • Yeah, meanwhile I saw the declaration in the header too... I will just rename my stupid variable and be happy that completion blocks do work. Yay... – Templar May 29 '14 at 14:03
  • I'm just curious, shouldn't the compiler be able detect situations like this ? I mean it warns me about all kinds of stupid local tableView declarations, but can't warn me if subclass property will overwrite superclass's ivar ? ... – Templar May 29 '14 at 14:12
  • A warning would be nice; maybe it just hasn't come up very often. You should [file a bug](http://bugreporter.apple.com) requesting that as a warning (at least). – Caleb May 29 '14 at 14:18
  • Yea, that's what I'll do next. Thanks. – Templar May 29 '14 at 14:28
-2

Don't use alloc/init to create a view controller. Ether load it from a storyboard using instantiateViewControllerWithIdentifier:, or load it from a nib using initWithNibName:bundle:.

That is likely the cause of your problem.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 2
    Why shouldn't you use `alloc ] init]`? If you aren't implementing a custom initializer, what's wrong with that? – Leandros May 29 '14 at 12:23
  • `initWithNibName:bundle:` is the designated initializer for view controllers. You would need to implement loadView and create the view controller's content view yourself, through code. – Duncan C May 29 '14 at 12:26
  • Well, if you call alloc init, the designated initializer `initwithNibName:bundle:` is still called, though. I'am actually doing this for many years now, without any issues. – Leandros May 29 '14 at 12:28
  • If I'am correct, Apple suggests to **never** call it outside of the `UIViewController`. – Leandros May 29 '14 at 12:33
  • Yeah, `alloc] init];` will actually look for a xib file with the same name as the class and use that if it exists. This shouldn't have any effect on running the completion block in this case though. – Fogmeister May 29 '14 at 13:43
  • @DuncanC I made a similar comment some time ago on another thread, and someone pointed out that `-init` is okay too. Here's part of the comment from `-initWithNibName:bundle:` in UIViewController.h: *The designated initializer. If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.)* You learn something new every day, right? Put your feet up... you're done until tomorrow. ;-) – Caleb May 29 '14 at 13:59