Window called with "showWindow" not focused - objective-c

i have a simple cocoa coredata statusbar application with Xcode 4.6.2. This is the situation:
Renamed MainMenu.xib to PreferencesWindow.xib, deleted the mainmenu, created a simple and working coredata function with arraycontrollers and bindings in the window.
I have created a new file->User Interface->Main Menu and named it StatusBarMenu.xib. Added a simple menu to it and removed the main menu.
Created new file->objective-c class->subclass of NSObject and named it StatusBarController.
Here's the code for the interface:
#property IBOutlet NSMenu *statusMenu;
#property NSStatusItem *statusItem;
#property [some items for statusbar image]
implementation:
#synthesize [everything]
-(void)awakeFromNib{
statusItem = [[NSStatusBar systemStatusBar]statusItemWithLength:NSVariableStatusItemLength];
[some string, path and stuff for the images]
statusItem.menu = statusMenu;
statusItem.toolTip = #"";
statusItem.highlightMode = YES;
}
Then I've created another new file->objective-c class->subclass of NSWindowController, named it PreferencesWindowController and leave it as it is.
Then a new file->objective-c class->subclass of NSObjects named PreferencesAppController. Here's the code for .h:
#property (assign) IBOutlet NSWindow *mainWindow;
#property (retain) PreferencesWindowController *prefController;
-(IBAction)showPreferences:(id)sender;
.m code:
#synthesize [everything];
-(IBAction)showPreferences:(id)sender{
if(!self.prefController)
self.prefController = [[PreferencesWindowController alloc] initWithWindowNibName:#"PreferencesWindow"];
[self.prefController showWindow:sender];
}
In the AppDelegate files there's only code for coredata, nothing added.
Then in the PreferencesWindow.xib I've added NSObject (the blue cube) for PreferencesAppController with some bindings: Outlets-> mainWindow binded to the window with the simple coredata function. AppDelegate has the window outlet binded to the same window, then Referencing Outlets->File's Owner delegate, some saveaction and managedobjectcontext.
In the StatusBarMenu.xib i've created a StatusBarController object and binded it to the menu (outlets->statusMenu), created another blue object called PreferencesAppController with Received Actions->showPreferences binded to a menu item.
Then i run the program and everything goes fine: an icon appears in the status bar, the dropdown menu works, if i click on "preferences..." the preferences window appears but... it isn't focused! It's on top of the other windows but i have to click to make it focused.
The coredata saving functions works fine except that i have to manually save with a button, quitting the application from the statusbar menu does not save, but this is a marginal issue.
Why isn't the window focused?

I'm assuming from your description of your app as a “statusbar application” that it is meant to run in the background and not show up in the Dock.
This means that your application is not the active application. The user clicking on your status item and choosing an item from its menu does not change that.
When an application that is not the active application opens a window, that window does not take focus (since this ordinarily would amount to stealing focus from whatever the user has been doing in the application that is active).
So, you need to activate your application.

Related

Access Property from Another Class, separate XIB

This might be an easy question, but bear with me I am very new and just experimenting. MacOS, Not iOS, let's say I have two separate XIB files (MainMenu.xib and AnotherWindow.xib). I am using the File Menu in MainMenu.xib to open AnotherWindow.xib, and disable the file menu when it opens with:
- (IBAction)OpenAnotherWindow:(id)sender {
if (!anotherWindow) {
anotherWindow = [[AnotherWindow alloc] initWithWindowNibName:#"AnotherWindow"];
}
[anotherWindow showWindow:self];
[self.MenuItem setEnabled:NO];
In the AnotherWindow.xib, I want to re-enable the file menu when it closes using:
- (void)windowWillClose:(NSNotification *)aNotification {
[self.MenuItem setEnabled:YES];
}
The problem I have is I am not able to access the MenuItem from the second class because it is part of MainMenu.xib - so I just get error: Property not found on object of type with the [self.MenuItem setEnabled:YES]; in the AnotherWindow.xib
So I guess my question is: How can I access a property like
#property (weak) IBOutlet NSMenuItem *MenuItem;
That is in my MainMenu.xib from AnotherWindow.xib.
Instead of manually enabling and disabling the menu item, override the function validateUserInterfaceItem in the class that contains the OpenAnotherWindow IBAction.
The validateUserInterfaceItem function takes an item of type NSValidatedUserInterfaceItem as an argument. Check if the item's action is OpenAnotherWindow. If it is, check if anotherWindow is open. If it's open, return false, which will disable the menu item. If the window isn't open, return true, which will enable the menu item. My Objective-C is rusty so I don't have a code listing for you.

(OSX/Cocoa) How to set controller for main window

I've created a new cocoa application using .xib files (not storyboarded, the app has to be backwards compatible with mavericks/mountain lion) and I would like to have a custom windowcontroller for the main window. Is this possible? I can't seem to find a way to connect the window to my desired custom controller. The window has a reference outlet in AppDelegate, however I need a custom NSWindowController for this window as it doesn't open on application launch. The application launches silently as a menu bar app and the main application is launched via button press in the drop down from the menu bar.
Is there a way to link a controller to the window in the interface builder? Or do I have to do something along the lines of :
wc = [[CustomWindowController alloc] initWithWindowNibName:#"Main"];
Thanks!
Yes, open up Utilities (the right panel) in Interface Builder, and at the bottom click on the Object Library (circle with square in it).
Search for Object (blue cube), and drag it into your Document Outline (the panel on the left inside of interface builder)
From there, select that object you just created, and change the Class in the Identity Inspector to be the window controller you want.
Finally you can go into the Connections Inspector and connect your window to the window outlet
I can't seem to find a way to connect the window to my desired custom
controller. The window has a reference outlet in AppDelegate, however
I need a custom NSWindowController for this window as it doesn't open
on application launch.
Another way:
1) Delete the window in MainMenu.xib. Delete the window property in AppDelegate.m--because you deleted the window, it is no longer relevant.
2) File>New>File>Cocoa Class. Enter a class name, e.g. MainWindowController; select "Subclass of: NSWindowController"; check "Also create .xib file for user interface".
3) Create an outlet in AppDelegate.m:
#import "AppDelegate.h"
#import "MainWindowController.h"
#interface AppDelegate ()
#property (strong, nonatomic) MainWindowController* windowController;
#end
4) Declare an action in AppDelegate.h:
#interface AppDelegate : NSObject <NSApplicationDelegate>
-(IBAction)launchWindow:(id)sender;
#end
and implement it in AppDelegate.m:
- (void)launchWindow:(id)sender {
[self setWindowController:[[MainWindowController alloc]
initWithWindowNibName:#"MainWindowController"]];
[[self windowController] showWindow:nil];
}
5) In MainMenu.xib, hook up the Menu Item to the launchWindow() action: control drag from the Menu Item to the AppDelegate object and select launchWindow.
Create the controller and make it extend from NSWindowController.
In your xib file select the File's Owner and set it to your custom class.
Select your NSWindow and connect it to the File's Owner.
To open the window:
In your .h:
#property (strong, nonatomic) YourWindowController *yourWinController;
In your .m:
self.yourWinController = [[YourWindowController alloc] initWithWindowNibName:#"YourWindowController"];
[self.yourWinController showWindow: nil];

display NSMenuItems list

I created a simple mac OS application and placed NSMenu in the nib file then I create two other files MenuManager.h and MenuManager.m where I created NSMenuIBOutlet and menu items etc. In MenuManager I have a method called setup which creates NSStatusItem and set menu to NSMenu which have created in header file as #property (weak) IBOutputlet NSMenu *menu;
In AppDelegate nib file I have selected Menu and refererenced outlet to menu object in MenuManager.
In AppDelegate I am calling method setup on MenuManager object which creates status item in status bar with image etc but when I click on it then list doens't appear.
Any idea where I am wrong?

How to enable main menu item "copy"?

My main menu item "copy" is not clickable:
But I enable it in Xcode:
I haven't any Outlets of Main menu items in code.
What I can do?
“Enabling Menu Items” in Application Menu and Pop-up List Programming Topics says this:
By default, every time a user event occurs, NSMenu automatically enables and disables each visible menu item. You can also force a menu to update using NSMenu’s update method.
and this:
If the menu item’s target is not set (that is, if it is nil—typically if the menu item is connected to First Responder) and the NSMenu object is not a contextual menu, then NSMenu uses the responder chain (described in “The Responder Chain” in Cocoa Event Handling Guide) to determine the target. If there is no object in the responder chain that implements the item’s action, the item is disabled.
If there is an object in the responder chain that implements the item’s action, NSMenu then checks to see if that object implements the validateMenuItem: or validateUserInterfaceItem: method. If it does not, then the menu item is enabled. If it does, then the enabled status of the menu item is determined by the return value of the method.
By default (when you create a project using the “Cocoa Application” template), the Copy menu item's target is First Responder (nil) and the action is copy:. So you need to implement the copy: method on some item in your responder chain. That is sufficient to enable the menu item. If you want more precise control of when the menu item is enabled, you can also implement validateMenuItem: to check which menu item is being validated and return YES or NO as appropriate.
For example, the application delegate is in the responder chain. So you can add this method to CMAppDelegate:
- (IBAction)copy:(id)sender {
NSLog(#"%# %s", self, __func__);
}
That should be sufficient to enable the Copy menu item. Of course, choosing Edit > Copy will just log a message to the console. It's up to you to actually write the code that copies whatever the user has selected.
If you want more granular control, try giving the app delegate an outlet connected to the Copy menu item:
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (strong) IBOutlet NSMenuItem *copyMenuItem;
#end
Hook up the outlet in MainMenu.xib. Then you can implement validateMenuItem: like this:
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
if (menuItem == self.copyMenuItem) {
NSLog(#"%# %s %#", self, __func__, menuItem);
return [self shouldEnableCopyMenuItem];
}
return NO;
}

uibutton hide and dropdown text

I have a signup button that switches screens for a signup form. I'd like for it to hide the button and drop down text boxes beneath when the button is tapped (instead of switching screens). Is this possible? Currently I have in my .h file...
#property (nonatomic, strong) IBOutlet UIButton *emailSignUp;
- (IBAction)hideButton:(id)sender;
and in the .m file my method is as follows
- (IBAction)hideButton:(id)sender {
[self.emailSignUp setHidden:YES];
}
However it seems to be crashing whenever I try to test. Any advice? I thank you guys in advance. I know there is a long way to go, but I feel this is my first step.
It sounds like you haven't connected the button you created in the Interface Builder portion of Xcode to the emailSignUp IBOutlet. You can do this by going to the Interface Builder, selecting File's Owner and then the Connection Navigator (in the right side panel, designated by the arrow icon in the tab bar). Then, drag from the Outlet to the button.