I am just learning and trying to put forth some of the knowledge with objective c and cocoa. I have a little program that has a login screen which then displays a main menu. On the main menu view, there is a button that should load a view to be able to add some data to the app. When I click on the button, it doesn't fire the IBAction but throws an error
EXC_BAD_ACCESS [StartMenuViewController performSelector:withObject:]: message sent to deallocated instance 0x6080195e9f90
I know that it is because there is an object that is not instantiated when the message is being sent, but I cannot find out why. Sorry for the code and the novice level here is the main menu view controller StartMenuViewController.m file:
#import "StartMenuViewController.h"
#import "AppDelegate.h"
#import "MasterViewController.h"
@interface StartMenuViewController ()
@end
@implementation StartMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
-(IBAction)showStrainView:(id)sender{
AppDelegate *delegate = nil;
delegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
MasterViewController *addStrainView = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
}
@end
here is the StartMenuViewController.h
#import <Cocoa/Cocoa.h>
@interface StartMenuViewController : NSViewController
@property (weak) IBOutlet NSButton *showStrainViewButton;
@end
Here is the AppDelegate.h
#import <Cocoa/Cocoa.h>
@class loginView, MasterViewController,StartMenuViewController;
@interface AppDelegate : NSObject <NSApplicationDelegate>{
loginView *loginView;
MasterViewController *masterViewController;
}
@property (assign) IBOutlet NSWindow *window;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (strong) loginView *loginView;
@property (strong) MasterViewController *masterViewController;
@property (strong) StartMenuViewController *starMenuViewController;
-(void)swapView:(NSView *)view1 toView:(NSView *)view2;
@end
Here is the AppDelegate.m
#import "AppDelegate.h"
#include "MasterViewController.h"
#import "ScaryBugDoc.h"
#import "Strains.h"
#import "loginView.h"
@interface AppDelegate()
@end
@implementation AppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize loginView;
@synthesize masterViewController;
@synthesize starMenuViewController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// 1. Create the master View Controller
self.loginView = [[loginView alloc] initWithNibName:@"loginView" bundle:nil];
// 2. Add the view controller to the Window's content view
[self.window.contentView addSubview:self.loginView.view];
self.loginView.view.frame = ((NSView*)self.window.contentView).bounds;
}
-(void)swapView:(NSView *)view1 toView:(NSView *)view2{
//[view1 removeFromSuperview];
[self.window.contentView addSubview:view2];
view2.frame = ((NSView*)self.window.contentView).bounds;
}
@end
If you need the loginView.h and loginView.m files I can add them as well. I would appreciate any and all help. Thanks in advance
The problem is here:
MasterViewController *addStrainView = [[MasterViewController alloc]initWithNibName:@"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
You don't keep a reference to the MasterViewController
so it gets deallocated even though its view is kept around. Now anytime the view tries to access methods from the view controller, things fail.
You should make addStrainView
a child view controller of self
in the above code so the view controller sticks around as long as its view.