0
votes

I have a simple app with a single view, on it there's a button. When clicking the button, it adds a 2nd view. This 2nd view has a simple toolbar with a single UIBarButtonItem on it. It is registered to fire a message of my view controller.

But as soon as I click the button the app crashes. Enabling Zombies, I see that my view controller got fired. Adding a dealloc function, with a call to NSLog(), I see that as soon as my view get visible, my view controller gets dismissed!

Also no message like shouldAutorotateToInterfaceOrientation is triggered.

My ViewController .h :

#import <UIKit/UIKit.h>

@interface IssueViewController : UIViewController
{
    IBOutlet UIBarButtonItem *button;
}

@property (nonatomic, readonly) UIBarButtonItem *button;

- (IBAction)buttonTapped:(id)sender;

+ (void)showSelfInView:(UIView *)view;

@end

Its .m :

#import "IssueViewController.h"

@interface IssueViewController ()

@end

@implementation IssueViewController

@synthesize button;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.button.target = self;
    self.button.action = @selector(buttonTapped:);

}

- (void)viewDidUnload
{
    NSLog(@"unloaded");
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)dealloc
{
    NSLog(@"Got dealloc");
}

+ (void)showSelfInView:(UIView *)view
{
    IssueViewController *ivc = [[IssueViewController alloc] init];
    [view addSubview:ivc.view];
}

- (IBAction)buttonTapped:(id)sender
{
    [self.view removeFromSuperview];
}


@end

Code used to trigger display of the 2nd view:

[IssueViewController showSelfInView:self.view];

Anyone knows what I'm doing wrong? Why doesn't my UIViewController get retained at least until the view get removed?

EDIT

I know about ARC, strong & weak references... In non ARC-code, in showSelfInView: I'd retain the view controller, and I would autorelease it in buttonTapped.

That's an ok way to achieve that, to me. And I would like to know if I'm missing something with ARC, or with the way I use my view/viewController. Since the view is still visible, to me, its viewController shouldn't get dealloc-ed. Is there any way to prevent that, besides of creating my own strong reference to the view controller?

REPHRASED

Is there any non-patchy non-dirty way to have a view controller remains allocated until its view gets removed from display. I consider any pointer from view controller to itself as dirty, though that's the way I'm currently using.

2

2 Answers

0
votes

You must keep a strong reference to the instance of IssueViewController if you don't want arc to release it right away (at the end of the scope where the instance is defined).

0
votes

Answer is: adding a viewcontroller's view as subview of a view of another viewcontroller is a bad practice and should be avoided.