Accessing objects on one nib file from another nib file - cocoa

I have two nib files - Main.nib and Preference.nib
In Main.nib file I have an instance of NSView class. Its window has a NSPopUpButton which on clicking shows a menu. In the menu I have show Preferences menu item.
Menu item on clicking shows a preferences panel containing a color well item.
On clicking color well a color panel is displayed to choose the color.
The problem is how to apply that color to main application window.
My preference panel window is in Preference.nib file.
So problem is accessing NSView from another Nib Window.
Is there a way so that I can make connection between preference panel and my main application window(NSView)

You're thinking about this at the wrong level. NSView and NSWindow are view objects in the Model-View-Controller pattern and shouldn't be used for holding application data. The color you select in your preference panel is application data and should be stored in an appropriate model object.
You could, for example, use bindings to bind the color well to the NSUserDefaultsController object to store that data (assuming this is an application-wide setting). You didn't say exactly what the color is used for in your main window, but if the object that uses it is bindings aware, you can bind that object to the same value on the NSUserDefaultsController and you're done.
Otherwise, you can respond to the color well's action message to store the color in an appropriate place and then send a notification using NSNotificationCenter to tell other objects that the color has changed. You'll need to sign up any object that needs to take action when the value changes for your notification message.
Here are some resources:
Here's an overview of the model-view-controller pattern that explains how Cocoa programs are structured
This is a high level explanation of how Cocoa bindings work
Here's a bunch of documents about using notifications

Related

NSTextField with automatic NSNumberFormatter in Interface Builder

I've been making iOS apps for awhile, but I'm trying my hand at MacOS development. I'm adding an NSTextField to my UI and I noticed in Xcode that one of the options in the graphical widgets is "NSTextField with NSNumberFormatter" which implies to me that I'll be able to restrict the input of the field to numbers and configure the formatter in some way.
When I add the NSTextField with NSNumberFormatter to my UI, I can see it has a formatter outlet which appears to be kind of linked to an NSNumberFormatter (although the name is a little grayed out). However, I can't figure out any way to interact with or configure that NSNumberFormatter.
Any help?
To access the NSNumberFormatter, you have to select it in the dock (that list of objects on the left side of the XCode 4 Interface Builder [IB] window).
If the dock isn't in outline view, e.g., it just shows about 4 icons, click the triangle-in-a-square-button at the bottom of the dock. The dock should now show a "Placeholders" section and an "Objects" section; the objects are your UI objects in a hierarchical outline view.
In the IB window, click your NSTextField; that'll highlight the corresponding Text Field Cell in the outline (you may have to twiddle down some disclosure triangles to see it). The Text Field Cell should have a disclosure triangle; twiddle it down to reveal the Number Formatter. Select it, and you should now be able to manipulate it in the Inspector panel.
(There are a lot of things non-obvious like that in XCode. When in doubt, examine your UI object in the Dock's outline view, or prowl the menus with that object selected. It's amazing--and often useful--what you can discover lurking there!
to configure the number formatter, you can ( after you've selected the formatter ) open the Attributes inspector, select the behavior you want and customize the formatter. At least that worked for me in XCode 4.
– moritz

Where is Core Data Entity in my Interface Builder Library?

I am trying to use the Core Data Entity in my app by dragging it onto a nib file within Interface Builder but it doesn't appear to be in my Library of controls.
Any idea how to get it in there?
Thanks
Graeme
I notice this is iOS tagged, so bad news: Core Data support in Interface Builder only exists for Macs, not iDevices (so far.) Make a MacOS X nib, not an ios nib, and you'll see "Managed Object Context" and "Core Data Entity" in the library. IB's Core Data support heavily uses Cocoa Bindings, which are also only available in MacOS proper (so far); without bindings it's not really meaningful to wire up model objects in the nib.
To see how to use core data without setting things up in IB, make a new iOS project with the "Navigation-Based Application" template, and check the "use core data for storage" checkbox. The meat is in the app delegate and RootViewController classes it creates; the nibs just contain VCs and UIViews, as normal.
The Core Data Entity doesn't exist in the Cocoa Library in Xcode 6.2. Instead, you can use an ArrayController.
1) Create a New project in Xcode: enter the project name and check the box that says Core Data.
2) In your project files, select the .xcdatamodeld file, and in interface builder setup an entity, which is like a Cocoa class with some #properties:
Click on Add Entity at the bottom of the window. In the image above, the entity is named Book. That line initially will say Entity instead of Book. Double click on Entity and type in Book.
Click the + in the attributes area to add the attributes and their types. To the far right, (with the rightmost icon selected at the top) you can check or uncheck other properties for the attribute, for instance uncheck optional.
As far as I can tell, setting up an entity is just like creating an Objective-C class with a bunch of #properties.
3) Select MainMenu.xib and drag a TableView(make it cell based) and a couple of square buttons onto the window:
For the buttons, in the Attributes Inspector next to Image, select NSAddTemplate and NSRemoveTemplate respectively. In the TableView, double click on the column headers and enter the column names.
Once you have your view set up, drag an ArrayController from the Library to the Dock. In the Identity Inspector, change the ArrayController's Label to BookController as shown in the image above. The label allows you to refer to that specific ArrayController, which is handy if you have multiple ArrayController’s in your xib file.
4) Next, in the Attributes Inspector specify the entity, or the type of the object, that the ArrayController will store and manage:
Also check Prepares Content. That will cause the data saved to disc to load in the TableView when the TableView launches.
5) With the ArrayController still selected, go to the Bindings Inspector, and under Parameters bind the ArrayController to AppDelegate and for the keypath enter managedObjectContext. The managedObjectContext is responsible for writing the data to disc:
6) Next, bind the columns of the TableView to the ArrayController. Make sure you are selecting the Book Title column:
In the Bindings Inspector under the Value binding, bind to the BookController(the label given to the ArrayController). The Controller key arrangedObjects is a sorted array of all the objects in the ArrayController. And by specifying the Model keypath as title, you are telling the column to display the title of every object in arrangedObjects.
Select the Author column in the NSTableView and setup the binding in a similar fashion.
7) Select the + square button, and Ctrl+drag from the button to the ArrayController. After releasing, choose add: from the popup menu. Then select the - square button, and Ctrl+drag from the button to the ArrayController. After releasing, chose remove: from the popup menu.
Finally, setup a binding for the - square button, which will disable the button when there are no items in the TableView to remove:
Run the application and use the + button to insert entries into the TableView. I notice that if I stop the application using Xcode's Stop button, the data entered into the TableView does not save to disc. Instead, I have to choose Quit under the application name in the menu bar in order to save the data to disc.

Multiple documents open at the same time, each with different menu item states

In a Cocoa document-based application, what's the best way to keep the menu item states in the menu bar in sync with the currently visible document?
For example, say you have a document with a ruler view that can be hidden/shown via "Show Rulers" (off state) and "Hide Rulers" (on state) menu items. The user has two documents open at the same time. He/she has hidden the rulers in one document, but not on the other. When the user moves between the documents the menu item should reflect the state for that document, not for the application as a whole.
How does one do this cleanly? I've googled around but it doesn't seem like there's a predefined "out of the box" way to do this. It would be nice if NSDocument had some sort of "didRegainFocus" type method where such logic can be added.
My actual implementation is a bit trickier since it's actually a NSViewController inside my NSDocument that deals with these particular menu items.
#interface MyDocument : NSDocument {
SomeViewController *myCustomizedTextViewController;
}
When MyDocument is the currently active document, I need methods in myCustomizedTextViewController to ensure the state of a couple of NSMenuItems in the application's main menu. One is genuinely a ruler. The other is a similar temporary setting.
Have the target of the menu items implement the validateUserInterfaceItem: method to enable/disable them. See the User Interface Validation reference for more info.

How do I make an NSPopupButton that has a menu with images AND text?

I have a list of applications and I'd like to make an NSPopupButton that shows a menu of application names with their icon to the left of each item.
I've been able to bind the NSPopupButton to my array of items, but there isn't a binding entry for an image. I thought I could put a cell in there and bind the cell as an image and as text, but I can't find an appropriate cell in IB.
Is there a clean and simple way to do this using bindings? Do I have to write a custom cell?
There is no way to bind the images as well as the titles of the menu items using a stock NSPopUpButton. You will have to subclass it and write an IBPlugin to expose the subclass. And, of course, you should handle the cell as well.
I've found mixing Bindings with NSPopUpButton to be a bag of hurt for a variety of reasons, including the impossibility of separators and of out-of-model menu items such as “Default” or “All”. Consider using a different control, such as a source list, or populating and re-populating the pop-up menu manually.
NSMenuItem has Image binding (in "Parameters" section waaaaaayyyyy down). So I think that you should bind that value to a path in your array of running applications. You can get an icon for your app using shared NSWorkspace object.

Launch window from NSView subclass in cocoa

Is it possible to launch a window in an NSView subclass by clicking a NSRect? I have tried makeKeyAndOrderFront but this doesn't work.
You can't click on a rectangle. A rectangle is just four numbers.
You can have an NSView that responds to clicks, but you should consider using NSButton instead. If you really want a custom view, you can both create the button and add it as a subview of your view programmatically. Then, set the button's target to yourself and its action to the selector of a message you'll respond to by opening the window.
One more thing: You don't launch a window. Windows aren't applications and applications aren't windows. On Mac OS X, applications have windows—always more than one (counting at least the About panel). So, you'll load the window from a nib, then make it key (respond to events) and order it front.
On that point: You probably should not have your view owning a window. Consider making a controller object to own the window instead, and having your view simply forward the message to the controller object (or even hook the button up to the controller directly).

Resources