I just started a new Cocoa project after a long time... And I don't know why, but I always get an error when calling a xib by a NSWindowController. What I do is really very simple: I have a new project as a starting point and then I don't wantz to call the xib from Appdelegate, but from a subclass of NSWindowController. Then the output tells me that:
2014-11-12 09:58:18.519 SimpleTest[8554:378690] ApplePersistence=NO
2014-11-12 09:58:18.671 SimpleTest[8554:378690] Failed to connect (window) outlet from (NSApplication) to (NSWindow): missing setter or instance variable
Okay, how does it look in code? My Appdelegate looks like this:
#import "AppDelegate.h"
#import "MainWindowController.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (strong) MainWindowController *mainWindowController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
_mainWindowController = [[MainWindowController alloc] initWithWindowNibName:#"MainMenu"];
[self.mainWindowController showWindow:self];
}
#end
Nothing special so far. The MainWindowController looks like this:
#import "MainWindowController.h"
#interface MainWindowController ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation MainWindowController
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self != nil)
{
//do something
}
return self;
}
#end
And again very simple... Additiponally I have some modifications in IB: File'Owner of MainMenu.xib becomes MainWindowController. Its 'window' outlet is connected to the Window of the application. The delegate of Window is connected to File's Owner. Well, that's it! But why do I receive this error? What am I doing wrong?
---EDIT---
this shows the connections in IB
The most important is using right selector to create new instance and having all wired up correctly.
Steps:
1. Add new xib with window or an empty one and add window to it
2.Select File owner and set it to NSWindowController or its subclass.
Select window and connect it to File owner
Make new NSWindowController instance
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:#"Window"];
[NSApp runModalForWindow:[windowController window]];
}
Related
I just like to play with coding for a hobby, so probably a noob question;
I have a simple storyboard for MacOS with 2 views. Both have there own classes (main class and subclass). How can I control a outlet in the subclass from the main class?
for example
I have a button (IBAction) in the mainclass and a textfield (IBOutlet) in the subclass. I want to set the stringvalue for the textfield with a click on the button in main.
I have searched a lot last days but just don't get it. (or just need a push in the right direction)
EDIT after JingJingTao's answer:
I used the control-drag function to open the second window.
I tried the code JingJingTao gives, but the textfield doesn't respond to the action.
My classes look like this now:
ViewController.h
#import <Cocoa/Cocoa.h>
#interface ViewController : NSViewController
- (IBAction)newText:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#property (nonatomic) ViewController2 *subclass;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
}
- (void)newText:(id)sender {
self.subclass.textField.stringValue = #"button pressed";
}
#end
ViewController2.h
#import "ViewController.h"
#interface ViewController2 : ViewController
#property (nonatomic) IBOutlet NSTextField *textField;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
}
#end
Update:
I've attached two screenshots of what it looks like in the storyboard for the first suggestion,
1) Add a view to your ViewController, set the class at the top right to 'YourView', 'YourView' is a just an NSView, add a textfield to it and hook it up.
2) Add YourView as a property to your ViewController, i.e. #property (nonatomic) IBOutlet NSView *yourView; and hook it up.
Let me know if there are any issues.
You just need to put the textfield in the public interface of your subclass, so you can access it in your main class, although it does sound like you're using inheritance and I don't think you need to but that's another topic :D.
Example:
In MainClassViewController.m
#interface MainClassViewController ()
#propert (nonatomic) Subclass *subclass;
#end
#implementation MainClassViewController
// I guess you already add your subclass to the main viewcontroller because they display on the same screen.
- (void)yourButtonTapMethod {
self.subclass.textfield.text = #"Your value";
}
In Subclass.h
#interface Subclass : NSObject
#property (nonatomic) IBOutlet UITextfield *textfield;
I use Cocoa Touch instead of Cocoa, so maybe it's NSTextfield for you. Please let me know if this does not answer your question, good luck.
I want to add a secondary window containing resources that can be dragged and dropped into NSDocuments.
My project contains:
1) ResourceWindow.xib
2) ViewController.xib
3) Main.storyboard
#interface AppDelegate ()
#property (nonatomic,strong)NSWindowController* wc;
#property (nonatomic, weak)NSWindow* resourceWindow;
#property (nonatomic, strong)ViewController* vc;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.wc = [[NSWindowController alloc]initWithWindowNibName:#"ResourceController.xib"];
self.resourceWindow = [self.wc window];
[self.wc showWindow:self];
self.vc = [[ViewController alloc]initWithNibName:nil bundle:nil];
[self.vc.view setFrame:[self.resourceWindow.contentView bounds]];
[self.resourceWindow.contentView addSubview:self.vc.view];
}
self.wc.window is nil immediately after allocating and initializing it.
Please set me straight on this.
Thanks
EDIT:
ResourceWindow.xib does not contain a window controller just a window . Is that the problem? Is the solution to drag and drop a custom object into the xib file and change it's class to NSWindowController?
In addition to the file name issue pointed to by Willeke, windows are nil until showWindow is called. Sigh. I started again by subclassing NSWindowManager and checking add xib file. Then, set the class of files owner to SourceWindowController and changed the code to:
#property (nonatomic,strong)SourceWindowController* wc;
#property (nonatomic, weak)NSWindow* resourceWindow;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.wc = [[SourceWindowController alloc]initWithWindowNibName:#"SourceWindowController"];
[self.wc showWindow:self.window];
self.resourceWindow = [self.wc window];
Running into a simple problem and not quite sure what is causing it. Linked a NSButton up to a ViewController xib. The property is referenced and then I linked up the IBAction to the view controllers view. I'm getting a crash whenever I press the button with an unrecognized selector message. I know I'm doing something wrong but on iOS this is pretty standard.
Here is the code:
#import "AppDelegate.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
IPVLocationViewController *mainViewController = [[IPVLocationViewController alloc]initWithNibName:#"IPVLocationViewController" bundle:nil];
self.window.contentView = mainViewController.view;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#end
#import "MainViewController.h"
#interface MainViewController ()
#property (weak) IBOutlet NSButton *mainButton;
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
- (IBAction)mainClick:(id)sender {
NSLog(#"THE BUTTON WAS CLICKED");
}
#end
In your Nib , it looks like your view controller instance is of type NSViewController instead of MainViewController.
So select the view controller in your Nib (or storyboard), and change its type to MainViewController.
Of course, if this view controller isn't being loaded from a nib or storyboard, then just check where you create it and make sure you created an instance of the correct class.
Solved it:
The accepted answer in this post helped me:
Needed to hold a reference to the view controller in the AppDelegate.
#interface AppDelegate ()
#property (nonatomic, strong) MainViewController *mainViewController;
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
self.mainViewController = [[MainViewController alloc]initWithNibName:#"MainViewController" bundle:nil];
self.window.contentView = self.mainViewController.view;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#end
I'm trying to make a Mac app by following a tutorial but Xcode comes up with the error property 'window' not found on object of type AppDelegate.
My code is
#import "AppDelegate.h"
#include "MasterViewController.h"
#interface AppDelegate()
#property (nonatomic,strong) IBOutlet MasterViewController *masterViewController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// 1. Create the master View Controller
self.masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
// 2. Add the view controller to the Window's content view
[self.window.contentView addSubview:self.masterViewController.view];
self.masterViewController.view.frame = ((NSView*)self.window.contentView).bounds;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#end
I don't know what this means or how to fix it.
Under #interface try adding:
#property (weak) IBOutlet NSWindow *window;
The error suggestions you haven't set the property for your window.
When create a project, uncheck the option "Use Storyboards". XCode will create a "window" property for you. See uncheck "Use Storyboards".
I am trying to implement a NSWindowController subclass with new xib-file, I read up in lots of books, and researched on StackOverflow, but none of the steps provided made my window show, nor did the subclass code get executed. The new xib-file has its File's Owner set to "LogNavigatorController" and connections to the window and its contents have been made.
My AppDelegate.h:
#import <Cocoa/Cocoa.h>
#class LogNavigatorWindowController;
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
LogNavigatorWindowController *logsWindowController;
}
#end
My AppDelegate.m:
#import "AppDelegate.h"
#import "LogNavigatorWindowController.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
logsWindowController = [[LogNavigatorWindowController alloc] initWithWindowNibName:#"LogNavigatorWindowController"];
[logsWindowController showWindow:self];
}
#end
My LogNavigatorWindowController.h:
#import <Cocoa/Cocoa.h>
#interface LogNavigatorWindowController : NSWindowController
{
NSArray *directoryList1;
NSArray *directoryList2;
NSMutableArray *directoryList;
NSMutableArray *filePaths1;
NSMutableArray *filePaths2;
}
#property (assign) IBOutlet NSWindow *window;
#property (weak) IBOutlet NSTableView *logsTableView;
#property (unsafe_unretained) IBOutlet NSTextView *logsTextView;
#property (assign) IBOutlet NSArrayController *LogListController;
#property (retain) NSMutableArray *logsArray;
- (void) myDirectoryLogFunction;
#end
My LogNavigatorController.m:
#import "LogNavigatorWindowController.h"
#interface LogNavigatorWindowController ()
#end
#implementation LogNavigatorWindowController
#synthesize logsTableView;
#synthesize logsTextView;
#synthesize window;
- (id)init
{
self = [super initWithWindowNibName:#"LogNavigatorWindowController"];
[self loadWindow];
[self showWindow:#"Log Navigator"];
[self.window makeKeyAndOrderFront:nil];
if (self)
{
// Initialization code here.
[self myDirectoryLogFunction];
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
- (void) myDirectoryLogFunction
{
NSLog(#"Code execution test successful");
}
#end
You don't need to create the window property since it is already available for NSWindowController subclasses. Maybe that causes the problem.
Also your init method contains a lot of code that doesn't belong there. Remove
[self loadWindow];
[self showWindow:#"Log Navigator"];
[self.window makeKeyAndOrderFront:nil];
as well as replace
self = [super initWithWindowNibName:#"LogNavigatorWindowController"];
with
self = [super init];
You may want to remove the init method at all, since you don't need it in your case.
and move
[self myDirectoryLogFunction];
to the windowDidLoad method.
Also always check that the code for instantiating the window controller (in your case from the app delegates didFinishLaunching: ) is called. Sometimes it helps to create a new project and test there, if you may have changed too much within the original project and by accident removed delegate connections or similar.