In Xcode, I'm making a Mac application in Objective-C. In designing my application's window, I realized there was an object called the User Defaults Controller in the Object Browser. What is this for? I know what the user defaults are, but what is the purpose of this in the object browser? What would be an example of when one would use this? Thanks!
The Controller's purpose is to bind your User Interface elements to the User Defaults.
As an example, you can have an NSTextField in your interface representing a configuration preference (for example default document title). You bind this to the User Defaults Controller. With this method the user can specify a default title that is being saved or updated automatically by the Cocoa Framework without writing a single line of code.
To to this, in IB put a controller and a textfield. In the bindings inspector, set the textfiled's String property to bind to the User Defaults Controller, set the Controller Key to values and set the Model Key Path to the key used in User Defaults.
It's used by Cocoa Bindings, to allow binding of UI elements to the NSUserDefaults.
Related
Unannounced, the 2 notices in the image below were discovered while searching for why -applicationShouldTerminate: is not being called in AppDelegate.m on quit (Cmd+Q). It worked some time ago.
Hovering over the two yellow triangles reveals:
NSObject does not have an outlet named delegate.
The action 'terminate:' is not defined on 'NSObject'.
Xcode is not showing errors or warnings and the app builds.
-applicationShouldTerminateAfterLastWindowClosed: IS called within AppDelegate.m when the red dot of the window is clicked.
My experience with Cocoa is thin (learning). I've compared the connections for File's Owner, Application and App Delegate in 2 other projects, and think a missing window outlet might be the cause. The notices above point to something else.
I would like to make sure the connections are correct as a first step. How do I repair this?
Edit: Add image of Main Window Controller connections
Edit 2: Add image of File's Owner connections
In the main NIB of an application, the two placeholders, File's Owner and Application, both end up referring to the same object. That object is the application object, the sole instance of NSApplication or a custom subclass of it. The Application placeholder is always holding the place of the application object because that's its purpose. The File's Owner placeholder is holding the place of whatever object is specified as the NIB's owner when it is loaded at run time. When Cocoa loads the main NIB at application startup, it specifies the application object as the owner. For other NIBs, File's Owner will likely be some other object.
However, Interface Builder doesn't know that a given NIB is the main one. So, it treats those two placeholders independently.
I don't know why Interface Builder has taken to setting the class of the Application placeholder to NSObject. It should really be NSApplication. That's why Interface Builder doesn't realize that the application object has a delegate outlet and an action method -terminate:.
As it happens, the class of File's Owner is properly set to NSApplication.
So, there are two ways to fix this:
Set the class of the Application placeholder to NSApplication or, in the rare case that you're using a subclass, that subclass.
Disconnect those connection from the Application placeholder and connect them to File's Owner instead. This is the way that the standard project templates do it.
For any given main NIB, you should probably standardize on using one or the other but not both. That is, one or the other should have no connections. That way you avoid conflicting or redundant connections.
I'm presenting a page based modal using [self presentControllerWithNames:self.controllerNames contexts:self.controllerContexts];, where controllerNames is just an NSArray of NSStrings containing my interface controllers names. The problem is that I would like to access the created controllers.
The documentations says that
WatchKit loads and initializes the new interface controllers and animates them into position on top of the current interface controller.
but I would like to have a reference to them, in order to call the becomeCurrentPage method from outside.
So, I would like to be able to save those controllers after they are created in a list, and programmatically change the page using something like [self.controllers[2] becomeCurrentPage].
Because you're allowed to provide a context when you present an interface controller, you can pass a reference to self. That way, you can establish a reference from the presented controller to its parent. Once that relationship exists, you can use things like delegation patterns to communicate.
I use this extensively in my own Watch app, and I've wrapped a lot of these mechanics in my JBInterfaceController subclass on GitHub.
I am just learning some Core Data and have run into an issue with the idea of having and being able to access separate stores for application-wide and document-only data.
I have a document based application that currently uses some of the entities within a managedObjectContext to populate a table via an NSArrayController.
However, some of these entities should be application wide (part of the experience for all documents - e.g. like data for buttons representing tools that are commonly used)
So for this reason, I pasted in the AppDelegate code for the non-document based application, which creates a separate, application-wide store and managedObjectContext, for the application. What I want to do is to access this MOC within each NSPersistentDocument (readonly) via an Array Controller (as before) to populate the table view of each opened document.
How would this best be done? And if this is not the way to populate a TableView that appears in each document from an application-wide MOC, which way should I look for?
P.S I am working in Swift, but am familiar with Objective-C - Thank you for any help!
According to Apple you should pass your MOC to the controller. From Core Data Snippets. Note the last two paragraphs.
By convention, you get a context from a view controller. You must implement your application appropriately, though, to follow this pattern.
When you implement a view controller that integrates with Core Data, you can add an NSManagedObjectContext property.
When you create a view controller, you pass it the context it should use. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.
A view controller typically shouldn’t retrieve the context from a global object such as the application delegate—this makes the application architecture rigid. Neither should a view controller create a context for its own use (unless it’s a nested context). This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.
Sometimes, though, it’s easier or more appropriate to retrieve the context from somewhere other than application or the document, or the view controller. Several objects you might use in a Core Data-based application keep a reference to a managed object context. A managed object itself has a reference to its own context, as do the various controller objects that support Core Data such as array and object controllers (NSArrayController and NSObjectController in OS X, and NSFetchedResultsController in iOS).
Retrieving the context from one of these objects has the advantage that if you re-architect your application, for example to make use of multiple contexts, your code is likely to remain valid. For example, if you have a managed object, and you want to create a new managed object that will be related to it, you can ask original object for its managed object context and create the new object using that. This will ensure that the new object you create is in the same context as the original.
Heys,
I am writing something in Xcode. I use Core Data for persistency and link the view and the model together with Cocoa Bindings; pretty much your ordinary Core Data application.
I have an array controller (NSArrayController) in my Xib. This has its managedObjectContext bound to the AppDelegate, as is convention, and tracks an entity. So far so good.
Now, the "Content Set" biding of this NSArrayController limits its content set (as you'd expect), by a keyPath from the selection in another NSArrayController (otherAc.selection.detailsOfMaster). This is the usual way to implement a Master-Detail relationship.
I want to variably change the key path at runtime, using other controls. This way, I sould return a content set that includes several other content sets, which is all advanced and beyond Interface Builder.
To achieve this, I think I should bind the Content Set to my AppDelegate instead. I have tried to do this, but don't know what methods to implement. If I just create the KVC methods (objectSet, setObjectSet), then I can provide a Content Set for the Array Controller in the contentSet method.
However, I don't think I'm binding this properly, because it doesn't "refresh". I'm new to binding; what do I need to implement to properly update the Content Set when other things, like the selection in the master NSArrayController, changes?
However, I don't think I'm binding this properly, because it doesn't "refresh".
This most often means you are assigning directly to the instance variable, not using KVC-compliant accessor methods nor posting KVO notifications.
The general solution is to create accessor methods for the property and then use them everywhere, including inside that class, except in its init and dealloc methods.
When I use Interface Builder > Inspector > Bindings to set up an binding for one of my view Items (i.e. an textfield), then I have to specify an object to which this view item will be bound to.
So I am wondering now, what exactly is the job of this object I specify in "Bind to:"?
I assume that Interface Builder automatically creates some methods which do all that synchronization stuff. Is that right?
And what does it mean when I "Bind to: File's Owner"? Is that my file with the main-Method inside?
… what exactly is the job of this object I specify in "Bind to:"?
You bind your view to your controller. The controller owns the model; the controller key you bind to is the name of a property that serves up some part of that model. The model objects have their own properties, and you may (in some cases must) provide a model key path along with the controller key.
I assume that Interface Builder automatically creates some methods which do all that synchronization stuff. Is that right?
Nope. IB never ever creates methods. The Bindings system does all that synchronization stuff, and it already exists. IB just calls it (specifically, it calls the bind:::: method I mentioned in my answer to your other question).
And what does it mean when I "Bind to: File's Owner"?
The File's Owner is the object that owns all the top-level objects in the nib file. The owner of the MainMenu nib is the application object (NSApp). In a document-based application, the document object will load a nib containing the document window; as such, it is the owner of the window, along with any other top-level objects in that nib.
Is that my file with the main-Method inside?
There's no such file, because there's no such method. There is a main function, but it's a function, not a method of an object. There's no object there, so you can't bind to it.
And you can't bind to a file, only an object. The source files disappear* when you link the program into a single executable. The executable contains only classes and functions, and the nibs contain objects (instances of the classes).
If you're asking which file is being owned, it's the nib file (or, more precisely, its contents—but “File's Contents' Owner” is a bit long).
*Well, except for debug symbols, which identify the filename and line number of each instruction.
The object you bind to has to be key value coding and key value observing compatible. Bindings is just a wrapper that use both those technics in a way that results in much less code.
If you really want to know how it works, there's an entry in Mike Ash's blog how KVO works..
I don't know if you want that much details. I suggest that you read the intro to bindings of cocoadevcentral.com. It makes a fairly good job at explaining them.
To your specific question about the File's Owner, Apple writes:
Each Cocoa application has a main nib
file that contains the
application-specific menus and
possibly one or more windows. NSApp
is File's Owner of the main nib
file. When an application launches,
NSApp loads the main nib file,
unarchiving it, and displays the menus
and initial windows.