tomiQrsd tomiQrsd - 5 months ago 29
iOS Question

IBAction not getting called from Subviews button click

So I spent my whole evening trying to solve my issue that is clicking Button located in UIViewController will not trigger IBAction.

My situation



I'm building my app using storyboard and my main ViewController is a TabBarViewController. One of the items of said TabBarViewController is, let's call it
MainViewController
.

Behind
MainViewController
there is
BackgroundViewController
which contains only camera preview and nothing else.

BackgroundViewController
was added inside
MainViewController
as follows:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
BackgrondViewController *bckgController = (BackgrondViewController *)[storyboard instantiateViewControllerWithIdentifier:@"background"];

[self.view addSubview:bckgController.view];
[self.view sendSubviewToBack:bckgController.view];


Everything works so far and I'm mentioning it becouse that might be relevant.

TopController



Now I want to add another ViewController to the
MainViewController
, this time on top. Let's call top view controller as
TopViewController
.

So first I instatiate it like this:

TopViewController *topController = (TopViewController *)[storyboard instantiateViewControllerWithIdentifier:@"top"];
topController.view.backgroundColor = [UIColor clearColor];


I added clearColor because there is need for that in my app and its confirmed that this changes nothing (trust me, I tried).

Okay now I add freshly created view as follows (we are still inside
MainViewController
)

[self.view addSubview:topController.view];
[self.view bringSubviewToFront:topController.view];


And it in fact does display transparent view with just a button in the center.

The Issue



No matter what I try I cannot make the button call its IBAction method.

Known facts and what I tried




  • TopViewController
    is actually on top of
    MainViewController
    views, I checked that by getting all subviews of
    MainViewController
    , taking the last element and comparing it to
    TopViewController
    's view.

  • IBAction is correctly linked to the Button I need to click (confirmed via storyboard and mousing-over methods outlet)

  • Adding
    TopViewController
    to TabBar works just fine, the Button does its job

  • The Button is visually clickable and it performs default animation when clicked

  • Setting
    topController.view.userInteractionEnabled = YES
    doesn't work

  • Adding single tap handler on
    TopViewController
    and clicking anywhere on screen doesn't work, however adding it to
    MainViewController
    does work (clicking anywhere on screen triggers defined action despite
    TopViewController
    being on top)

  • All sizes, id's and corresponding classes are verified

  • viewDidLoad
    of
    TopViewController
    is getting called



Please help me get out of this jam. Thanks!

Answer

Are you retaining topController by using an instance variable or property?

A simple way to do this is to create a property in your MainViewController.h file.

@interface MainViewController : UIViewController
    @property (nonatomic, strong) TopViewController *topViewController;
@end

Or at the top of your MainViewController.m file

@interface MainViewController ()
    @property (nonatomic, strong) TopViewController *topViewController;
@end

Then set the property any time after you created it.

self.topViewController = topController;

Explanation

-[UIView addSubview:] retains the view, but not the view controller. If you do not retain the view controller, then ARC will release the view controller at the end of the function. You can verify this by overriding -[TopViewController dealloc]. When you press the button, it tries to send a message to a now nil view controller.

Comments