Cocoa custom view for NSMenuItem - cocoa

I am developing a small app that display the active mounts in a menu in the NSStatusBar. So far it looks like this:
I want to add an eject button to the right of each menu item (like the left bar in the Finder). I know that I have to create a custom view and set it with the setView: method. The problem is that I am very new to Cocoa and right now I don't know how to dive into the custom view topic. Actually, I programmed a lot but never worked with interfaces so far :). Does anyone of you have a good tutorial for adding a custom view to a NSMenuItem?
I think this app will be very handy because you can hide the mounted icons from your desktop. The problem is that you always have to go back to the finder to unmount a volume...
Thanks for any help or tips you have!

It doesn't have to be a custom view. It can just be a standard NSView that acts as a container for standard controls.
The tricky part for a newbie is making the view reusable. You'll want your own NSViewController subclass with a corresponding view nib/xib (set up with your name label and eject button). For each menu item, you'll instantiate a new NSViewController with the XIB ( -initWithNibName:bundle: ) and set its represented object to your mount point. Your view controller subclass will have all it needs to respond to the eject button click, set the label to its represented object's path, etc.

Related

Linking actions to buttons on a modal/popover segue (swift 2 Xcode 7)

I'm sure I'm asking a simple question but I've only just started coding... so take pity on me!
I'm trying to figure out how to connect buttons (actions) to the viewController.swift from a modal/popover segue (I think the solution is the class but whenever I change it I get an error).
Eg.
In the storyboard, on the viewController interface, I have a button for sharing files. When I click it, a popover segue appears with two buttons on it, one for Fb one for Twitter, but I can't connect any actions from them to the viewController.swift
In another project I made a Google+ login and connected it to a modal segue but I couldn't make that work either.
Is segue the wrong thing to use?
Thanks for your help!
Marie
Your question would be easier to answer if you'd provide the actual error you're getting when you try to change the class.
It sounds like you're trying to connect the popover's buttons to actions in the presenting view controller (that is, the view controller that presented the popover), rather than the view controller of the popover itself. If that's the case, then that's the problem. You can only connect your buttons directly to actions available in the current scene.
This means you need a custom class for the presenting view controller (the one with the button that segues to the popover controller) and one for your popover. Set each scene view controller's classes to the appropriate custom classes you created (which must be a subclass of NSViewController or one of its subclasses or you won't be able to set the class name in IB) and you should be able to drag connections.

Accessing menu items from view controller in a storyboard, OS X, swift

I am building an OS X app in Xcode using storyboards. I have found that working with menu items is difficult and non-intuitive. The menu items are in a different scene (the application) than the view controller, and can not be connected to the view controller by the usual control-drag methods to create an outlet/action. I need to access menu items from the main view controller. I have figured out how to connect actions via first responder chain. However, I also would like to enable/disable menu items from the view controller, and I see no way to create an outlet to be able to do this.
I am new to OS X programming. I feel like I am missing something very basic here. I have watched several WWDC videos related to storyboards, and have not seen a good example showing the proper way to work with menus. Any help would be most appreciated.
There are several ways to work with menus. The traditional Cocoa way is to add an action method to First Responder proxy in IB.
Then flesh out the same action method in the NSResponder subclass that you want. Declare it in the header too.
This will then receive the action message via the Responder Chain.
Read up on the Responder Chain.

NSWindow vs ViewController - OS X - Cocoa

I have been making iOS apps for a while now and I decided that I wanted to start working on making some of them for the Mac too.
The question I have is this: is there any need for an NSWindow, now that developing for the Mac is so similar to iOS??
So I made a simple cocoa application using Xcode and its comes with a storyboard called "Main", just like on iOS.
In that storyboard file, there is a NSWindow which then links to a NSViewController.
Can I get rid of that NSWindow? As I tried setting the NSViewController as the "Initial Controller" and the app still works fine. So whats the point of the NSWindow?
Also, what class links to the NSWindow? I was trying to blur that background of the NSWindow, but I have no way of linking code to the NSWindow.
Sorry for my stupid questions, but I am completely new to development for OS X.
Thanks for your time, Dan.
Those are many questions in one question:
Can I get rid of NSwindow? No, you need a window to show you views.
What is the point of the NSWindow? NSWindow is needed as the window in which the views are displayed and your events are going up the responder chain.
What class is linked to NSWindow? Obviously the NSWindow class, but that is not what you want to know. I think you want to know the delegate that controls NSWindow. This is NSWindowController, although for the MainMenu.xib it is NSAppDelegate.
Hope this gives you the answers you need. An example for working with views in a window is given in this question.
Please, see for further details the windows programming guide, which states:
The NSWindow class defines objects that manage and coordinate the
windows an application displays on the screen. A single NSWindow
object corresponds to at most one onscreen window. The two principal
functions of an NSWindow object are to provide an area in which NSView
objects can be placed and to accept and distribute, to the appropriate
views, events the user instigates through actions with the mouse and
keyboard.
For the question: Can I get rid of NSwindow? I have further comments. In most cases, You need a NSWindow to show view on screen; but in special case you don't, for example, a popup view when you click a NSStatusItem.
So my answer is whenever you need to respond window event such as min/max, you need NSWindow as the view container.

In Xcode, how do I create an outlet for a button that is inside a container?

I'm a total newbie with xcode and swift, trying to wrap my head around ios programming.
I'm designing a storyboard for my app. The storyboard uses containers to keep track of the controls. In one of the containers resides a button. I want to create an outlet for it to add some code when it is clicked.
If the button would be on the base viewport of the storyboard, I would control-drag a blue line from the button to the source window with my UIViewController subclass file, and it would assist me in generating the code. But for some reason when the button is in a container, this just doesn't work.
When following the documentation, it says to open the assistant editor when the button is selected and it should open the relevant file. So it open an objective-c file, but when I try to control-drag into it, it informs me that I do not have write permissions. Also I feel like I should be doing it in a subclass instead.
I have searched online a lot and tried everything I can think about, but nothing has worked so far. How does this work? Can I do it programmatically or so perhaps? I hope someone can straighten out this question mark...
A container view is intended to represent an area that will host a view from a different view controller that becomes a child of the view controller that owns the container. Usually, you would create a second view controller, link your container view to it using an "embed" segue, and then put your buttons and such in the second controller's view. The code behind those would then go into the second controller.
If your purpose is simply to have superviews to control layout within a single view controller, use a UIView rather than a container and the problem goes away. That's what the Editor->Embed In->View menu item is for.

High-Level App Design/Architecture

I've done a fair amount of iOS development in the past couple of years, so I'm pretty familiar with iOS architecture and app design (everything's a ViewController that you either push, pop, or stick into tab bars). I've recently started exploring proper Mac app development and feel a little lost. I'd like to really just have a sanity check and maybe some advice as to what the proper way to build an app like this is:
I'd like to build a library-style, single window app, that will spawn additional windows during its operation, but not as full-blown documents. The main window will be laid out much like OS X Lion's Mail.app, with a three-wide split view containing:
A source list, or high-level topic selection
A list view of items pertaining to the topic selected in the first pane
A detail view, which shows the details of the object selected in the middle pane
Like I said, really similar to Mail.app as far as looks go.
My question is really how to glue all this together from inside XCode. Here's where my confusion lies so far:
The default project generated a NIB with a main menu and window. I like to encapsulate functionality, so should I make a window controller for this window and somehow hook it up in Interface Builder, or does window-specific functionality belong somewhere else?
If possible, I'd like each of my three panes to be separate view controllers. I created three NSViewController subclasses (XCode automatically generated NIBs), and added (to the main menu/window NIB) view controller objects with each class specified, hooking up each one's view property to one of the three Custom View generic NSView objects I dropped into the NSSplitView. When I tried to set each view controller's NIB, only the main menu/window NIB appeared in the drop-down, and typing the desired one by hand seemed to have no effect (the view's contents didn't actually appear when running the app). This makes me think I'm doing something wrong.
I'm a little fuzzy on what types of views I should use for each of the first two panes. I'll obviously build a custom one for the final pane, but it seems like the first two should be present in the Cocoa framework already.
Anyway, if I'm doing completely the wrong thing, don't bother addressing my questions; just tell me what I should be doing instead. I think I just need a proper Mac developer to point me in the right direction.
With regard to your first question, you don't need to use the main window that Apple supplies in MainMenu.xib. If you want, you are free to delete that window from the nib and then instantiate an NSWindowController in your applicationDidFinishLaunching: delegate method which then loads and controls the main window.
You are definitely confused about NSViewController, which is not really all that surprising, since you might assume that it works like UIViewController.
In fact, NSViewController is completely different to UIViewController and does not have the same level of Interface Builder support. You can't place a view controller in a window in IB, for example, whereas this is standard practice on iOS. NSViewController is a relatively new class on the Mac and generally you use it to load views programmatically and manage the view content.
The class that most closely maps to UIViewController on the Mac is NSWindowController. This has been around a lot longer than NSViewController and in fact many Mac apps don't use NSViewController at all.
Generally, each window in your app should have a window controller managing it. You can use subclasses of NSWindowController to handle a lot of the functionality for each window.
If you want to use NSViewController, then you should use your window controller to manage those view controller objects. This is generally done programmatically due to the aforesaid lack of Interface Builder support. Each NSViewController instance loads its view from a specific nib file. You generally don't add view controllers in Interface Builder.
For your source list you would generally use an NSOutlineView if you have multiple sections or an NSTableView. These two objects are used whenever you need a list of items. NSOutlineView is hierarchical, whereas NSTableView is flat.
I hope this helps.

Resources