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
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:
Modify:
(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.