Joseph
Joseph

Reputation: 9351

ARC seems to be releasing the view of my NSViewController

I am trying to solve a larger problem and I am tipping on the fact that ARC apparently is releasing the view to my NSViewController too early. I think :) So I created a simple app to reconstruct the situation.

I have a simple ARC Cocoa application. In the Window of the MainMenu.xib I hook up a Custom View to a @property (strong) IBOutlet NSView *theView; which is declared in the AppDelegate.h

In the AppDelegate.m I synthesize the property and then call the following:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    TestViewController *tvc =  [[TestViewController alloc] initWithNibName:@"TestViewController" bundle:nil];
    [_theView addSubview:[tvc view]];
}  

The TestViewControllergets displayed in the Custom View - no problem. It contains one NSButton. It is hooked up to a method called -(IBAction)btnPressed:(id)sender and one NSTextView which is also hooked up as an IBOutlet.

In the TestViewController.h I declare:

@property (nonatomic, strong) IBOutlet NSTextField *textField;
@property (nonatomic, strong) NSString *theString;

-(IBAction)btnPressed:(id)sender;

In the TestViewController.m I then do

@synthesize theString = _theString;
@synthesize textField = _textField;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Initialization code here.
        _theString = @"Hello World";
    }

    return self;
}

-(IBAction)btnPressed:(id)sender
{
    [_textField setStringValue:_theString];
}

When I run the app and press the button it crashes. If I check it for zombies I receive the following:

#   Address Category    Event Type  RefCt   Timestamp   Size    Responsible Library Responsible Caller
0   0x7f97a3047560  TestViewController  Malloc  1   00:00.652.631   128 TestARC -[AppDelegate applicationDidFinishLaunching:]
1   0x7f97a3047560  TestViewController  Retain  2   00:00.653.088   0   TestARC -[TestViewController initWithNibName:bundle:]
2   0x7f97a3047560  TestViewController  Release 1   00:00.653.089   0   TestARC -[TestViewController initWithNibName:bundle:]
3   0x7f97a3047560  TestViewController  Retain  2   00:00.653.912   0   AppKit  -[NSNib instantiateNibWithOwner:topLevelObjects:]
4   0x7f97a3047560  TestViewController  Release 1   00:00.658.831   0   AppKit  -[NSNib instantiateNibWithOwner:topLevelObjects:]
5   0x7f97a3047560  TestViewController  Release 0   00:00.662.377   0   Foundation  -[NSNotificationCenter postNotificationName:object:userInfo:]
6   0x7f97a3047560  TestViewController  Zombie  -1  00:01.951.377   0   AppKit  -[NSApplication sendAction:to:from:]

What am I doing wrong? Thanks

Upvotes: 0

Views: 741

Answers (2)

Phillip Mills
Phillip Mills

Reputation: 31016

Add a property to hold the view controller. Your controller currently has nothing to keep it alive past the end of the method that allocates it.

Add:

@property (strong) TestViewController *tvc;

Modify:

self.tvc =  [[TestViewController alloc] initWithNibName:@"TestViewController" bundle:nil];

(I'm curious...what do you see as the point of creating a view controller if all you want is the view it contains?)


Concerning the general approach, it seems that this is more properly behavior that should be implemented using a container view controller. That mechanism allows multiple view controllers to share the screen in an organized way.

Upvotes: 2

BJ Homer
BJ Homer

Reputation: 49034

You need to add an ivar or property to hold the TextViewController. Currently, the only reference to it is going away at the end of applicationDidFinishLaunching: which causes it to be deallocated.

That's bad, because your button needs the controller to be around to handle the button press. The view doesn't hold on to it's controller, as that would cause a retain cycle. So you are responsible for keeping the controller around if you don't want your button talking to a deallocated object.

Upvotes: 0

Related Questions