NSApplication mainMenu returns nil - objective-c

the problem I'm having is I cannot add a menu to my app programmatically!
here's where I'm at:
in app delegate
applicationDidFinishLaunching:
create a window and make key and order front.
EDIT:( here if I log [NSApplication sharedApplication].mainMenu prints (null) ) anyway...
create a NSMenu object and [[NSApplication sharedApplication] setMainMenu:myMenu]
also tried [[NSApplication sharedApplication] setMenu:myMenu]
build/run
menu is not there!
EDIT2:
( if still not understanding: )
make a osx app, remove the menu object, run, you'll still see a menu up there with the name of your app, you click it, it turns blue but no submenus, now how do I get a pointer to that!

You won't be able to do this as the OSX menus conform to the Aqua layout. Is there any reason why you'd remove it completely?
It's probably going to be a nightmare for a few reasons:
1) In the standard 'Aqua Menu' you have menu's like 'Services' which are handled by the system and not by the Application.
2) Apple are specific about their design guides, and menu's aren't mentioned and I'd HIGHLY doubt it apple would like you changing the Aqua layout.
I remember once upon a time coming upon a discussion which mentioned setAppleMenu etc... but that was back in the Tiger (I think) days.
edit you won't be able to get a 'pointer; to it using Documented API's, it's system-driven, not application driven i.e. complying with Aqua.
Personally, I'd remove all of the menuItems which can be changed in a sandboxed app, i.e. in User Land, and add/remove the various menuItems yourself.

Related

Define a controller for NSDocument for document-based application

I'm not very sure how Document-Based Applications works.
I've created some actions for NSObject in the Mainmenu.xib. One of this is called when the user click on "File>new":
-(IBAction) newDocument:(id)sender{
Document* newDoc =[[Document alloc] init];
[[NSDocumentController sharedDocumentController]addDocument:newDoc];
[newDoc addWindowController: [[NSWindowController alloc] initWithWindowNibName:[newDoc windowNibName] owner:newDoc]];
[newDoc showWindows];
}
I've also this code inside the openDocument:(id) sender action that does the same but of course loading data to define the application workspace.
If I run the application it show a blank document without to call newDocument action. I don't know how to stop default blank document and to set newDocument: to be called.
Then if i do openDocument: too (so I've two documents, one blank and one not) and I do some operation on the second document it also replicate in the first blank one.
I've double check delegates, file owners, and also if the - (void)windowDidBecomeMain:(NSNotification *)notification return different pointers and all seem to be ok.
Probably I've not understood document based application work flow but I've read the Apple guide and other istructions. What do I miss?
An IBAction method is called, when the user did something. So this is not called from the system at app launch.
You can customize the behavior at app launch with -applicationShouldOpenUntitledFile: (NSApplicationDelegate) and – this is probably your next question – -applicationShouldHandleReopen:hasVisibleWindows: (NSApplicationDelegate). Changing the behavior in both cases is not recommended.
Looking to your action method, I see no reason, why you want to customize it.
A instance of your document class is created automatically.
You can create a window controller for it in your document subclass. This is documented.
Just let NSDocumentController do the work for you. What is the problem of the default behavior?
No. I thought to be confused instead the only problem was about releasing observer notification. When you call the close message for a NSDocument notification observers still persist. Working in ARC I miss this point.
So This is the solution at my issue. Thank you anyway.

Catch key events in a NSWindow

I'm trying to get a very basic web browser with 3 Webviews (2 hidden and 1 visible at all times).
I'd like to switch between these 3 webviews by pressing CMD+1, CMD+2, CMD+3.
I have created a basic Cocoa app, added 3 webviews in it, referenced the Webkit framework and I'm up and running with it, this part is working.
Now I wonder:
1) How to catch key event? It seems so overly complicated that browsing the event structure docs gave me a headache.
[rant]From someone who did lots of Windows forms, GTK, QT and Java/C#/C++ work it seems that XCode is getting worse every release by moving everything around and creating 3 different ways of achieving the same thing, etc. Each time I have to use it's always like I have to learn everything once again.[/rant]
2) How to specifically catch CMD+NUMBERS ?
This is just for a quick productivity app I'm building to use in conjunction with JIRA (project management).
I'd appreciate if somebody could point me in the good direction.
Every time I stumble upon a good tutorial, it was outdated or was for iOS dev which most of the time doesn't use the same APIs as OS X anymore.
Sorry about the rant and thanks about your help!
What you are looking to override is the NSResponder method "keyDown:", and what I would recommend doing is subclassing "WebView" and create your own "keyDown" method (make certain to call "[super keyDown: theEvent]" somewhere in your implementation, though).
Now, within your "keyDown" implementation, to look for the command key, "NSEvent" objects respond to the "modifierFlags" method and one of the flags is "NSCommandKeyMask".
E.G.:
NSUInteger flags = [theEvent modifierFlags];
if( flags == NSCommandKeyMask ){
// Got it!
}
Don't worry about what kind of views they are.
Put each one inside a tab of an NSTabView, with or without tab control displayed.
With tab control, set the desired key combo per tab in IB.
With or without it, create a menu item in a menu in the menu bar for each tab with the same key combos. This is the recommended way since long ago. Apple recommends adding a menu bar menu item for everything that has a keyboard shortcut. The menu bar will receive the keys before anything else.

Xcode: How should I organize my multi-window user-interface project?

Note: Using Objective-C, Cocoa, and Xcode.
At first, I did all my programming in the AppDelegate and had all user-interface elements such as windows in the same '.xib' (nib file). This worked great at first, but then as my application became more advanced with more "features", everything became extremely cluttered and the file too long for my liking.
I'm now trying to progress. I'm wondering how I should (properly and efficiently) go about having a multi-window project? My plan was to have a .xib file for every window, and put only necessary things in the AppDelegate. I would then have a core file for all necessary calculations and such to be used in my application and a Main Controller file to control outlets and actions from all windows in my app. However, I'm quite new to Objective-C and have been running into SO many issues and problems trying to set up Window Controllers and stuff.
Am I even on the right path? Am I doing it wrong? How should I manage a multi-window user-interface application in Xcode?
Thanks in advance.
For multiple windows, I think it's best to use an NSWindowController for each, with it's associated xib file for the window. I'm not sure what you mean by "a Main Controller file to control outlets and actions from all windows" -- each window controller will have outlets to its own window. You can't connect outlets across multiple xib files. You can have one window in the MainMenu.xib file that you get by default when you create a project, and use that to launch other windows perhaps, but it's hard to offer any more specific advice without knowing how all your windows relate to each other.
After Edit:
If you want to open another window, have a menu item's action method be something like this:
self.controller = [[WindowController alloc] initWithWindowNibName:#"WindowController"];
[self.controller showWindow:nil];
Here, I have a property called controller to keep a strong reference to the new window controller. If you don't do that, the controller will be deallocated, so if you have multiple windows, that you want to show at the same time, you'll need properties to hold on to them.

How do I use a RootViewController when making an app without a ViewController?

I am trying to make a simple app from a tutorial that does not have a viewController at all. All the code is in the AppDelegate. I am on xcode 4.2 and I am getting this error:
Applications are expected to have a root view controller at the end of application launch
I'm not sure how to deal with this. There are some blogs out there with fixes but none of them are working for me and I really would like to understand what is going on here. And, how to fix it.
I do have a view that contains some buttons and labels. But I have no "ViewController". The files contained in my project are: AppDelegate.h, AppDelegate.m, and Window.xib only. There is no ViewController.h, ViewController.m
** edit **
I ended up making the app from a 'view based application' instead and just moving all the logic from the app delegate to the view controller. So, I didn't really solve the problem per se. The app works now though. Thanks for the help
It's not possible to have an iOS app that doesn't have a view controller. You can always create a trivial view controller, i.e.,
[[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds].rootViewController =
[[[UIViewController alloc] init] autorelease];
It sounds like you're looking at an old tutorial. UIWindow got a rooViewController property in iOS4. I believe it became required in iOS5 to help keep controller hierarchies and view hierarchies in sync with the addition of custom container controllers (and to fix a corner case where replacing the "root controller" of a UIWindow could stop orientation changes from propagating). There was a WWDC presentation in 2011 that explained this in some detail. I think it was Session 102, Implementing UIViewController Containment.
At then end of the day, there's no good reason not to have a root view controller. Apple wants to be able to assume it's there in their APIs going forward. If the tutorial you're looking at doesn't account for that, it's broken.
While I agree that there may be workarounds, another question to address is: why do you want an app without a view? Even if it's designed to run in the background and present no visual interface, at least make a simple view showing the application name and version, a largeish icon and perhaps a status. This kind of idle screen uses very little system resources, especially when the app is backgrounded, but improves the overall experience of the app.
If you set your deployment target to 4.3 and run on the iPhone 4.3 simulator, you won't get the warning.
To install the iOS 4.3 simulator, go to Xcode > Preferences > Downloads.

How to make a Mac OSX Cocoa application fullscreen?

I have been trying to make my Mac application enter fullscreen now for a while but can't get it to work. According to the Apple developer center, I should use enterFullScreenMode:withOptions: which gives me, method enterFullScreenMode not found.
Everywhere I google there seems to be people having issues with making their app fullscreen, so what is the way to make it work?
Edit:
Of course enterFullScreenMode is for the NSView and I used it on a NSWindow; it's not the view I want to have fullscreen, but the window. I can't find any function for the NSWindow though.
Lion has some new APIs for full screen.
To do it with NSWindow, do this
[window setCollectionBehavior:
NSWindowCollectionBehaviorFullScreenPrimary];
To do this with NSApplication do this
[[NSApplication sharedApplication]
setPresentationOptions:NSFullScreenWindowMask];
A bit more about it here.
Modern day Mac Os X developers (who use storyboard) need only to click on their main.storyboard, select the NSWindow (not the NSWindowController), Use the right panel to find the attributes panel (the one that to the left of the ruler, it looks like a drag-bar thing) look for "Full Screen" and select "Primary Window" rather than its default value of "Unsupported". You can also set up Auxiliary windows if that's what you want.
Don't fight the change, use storyboard. One of us... one of us...
As mentioned in the link Jonathan provided in the comments, enterFullScreen:withOptions: has a number of drawbacks that can make you want to tear your hair out. The best way to do fullscreen is still the older CGDirectDisplay API. Cocoa Dev Central has an article on fullscreen apps that covers pretty much everything you need to know.
You'll notice the article is pretty ancient and the dev tools have changed a lot since then (Project Builder! Ah, the good old days), but the code itself will still work.
[self.view setFrame:[[NSScreen mainScreen] visibleFrame]];