Files owner and nsapplication, appdelegate - objective-c

In the apple docs it states that nsapplication is the file owner of the main nib. Is this just set up by the template or must the first nib to be loaded, be loaded in this way?
Also, I read through the rest of the posts about the file owner and something still confuses me. Can IBoutlets only point to objects, if the Iboutlet is a property of the nibs file owner, and the object is found within that nib? Why does the nib even need to know the class of it's owner In addition to the object? What is enabled or disable by knowing or not knowing this?
One more, where does the appdelegate fit into this picture? Can you even change the app delegate?
Thanks :-)

Xcode's application template sets up MainMenu.xib to be loaded with NSApp as its owner. This is done by the NSApplicationMain function. NSApplicationMain looks up the NSMainNibFile key in the app's Info.plist file. If it finds that key, it uses the corresponding value as the name of the nib file to load. Xcode's app template sets NSMainNibFile to MainMenu.
It doesn't have to be done that way. You can change or delete the NSMainNibFile entry in Info.plist. You could even not use NSApplicationMain. Instead you could initialize NSApp yourself (by calling [NSApplication sharedApplication]), and then create your user interface programmatically or by loading nibs, and then call [NSApp run].
The nib loader can only connect outlets to objects in the nib it's loading, or to File's Owner, First Responder, or Application. The outlet itself doesn't have to be on File's Owner; it can be on any object in the nib.
When you set the class of File's owner, Interface Builder scans your source code to find the declaration of that class. That's how it knows which outlets and actions File's Owner should have.
The app delegate is generally the top-level controller for the application. It is notified when a variety of application-level events occur. Look at the NSApplicationDelegate Protocol Reference.
In Xcode's app template, the application delegate is an object in MainMenu.xib (you can have non-user-interface objects in a nib), which is wired to File Owner's delegate outlet. You can modify the class however you want. You can even delete the object from the nib entirely. But any serious app will need an app delegate.

Related

AppDelegate instantiated last on launch

I'm very comfortable with writing iOS apps, but OS X unexpectedly seems somewhat alien.
Here's the question upfront (read on for context):
When my application launches using the .xib set in the Main Interface field under the deployment info of my apps target, why does the AppDelegate get instantiated after the ViewControllers?
Context (no pun intended):
The reason I ask is because I'm using Core Data (spare me any heckling for this decision), and typically you keep a pointer to the MOC (Managed Object Context) in AppDelegate. One of my controllers is trying to get this MOC instance variable but the AppDelegate instance isn't around yet and therefore my app doesn't present data just after launch.
The AppDelegate and the two ViewControllers are in the .xib. The VCs are hooked to views inside a split view. They're trying to use the MOC in viewDidLoad to make queries. They are accessing the AppDelegate like this:
let delegate = NSApplication.sharedApplication().delegate as AppDelegate
let moc = delegate.managedObjectContext
This will crash as the .delegate property of the sharedApplication() returns nil.
I tried making an NSWindowController from the .xib in applicationDidFinishLaunching and removing the .xib from the Main Interface field, but then applicationDidFinishLaunching doesn't get called at all.
I've ensured that all the connections in IB for from the Application and the Files Owner (NSApplcation) delegate IBOutlets to the AppDelegate have been made.
UPDATE - 31/03/15
Stephen Darlington's answer below offers a good solution for my/this case. And as I understand it's actually better to setup the MOC in the way he's suggested.
If a correct answer arrives that explains why the AppDelegate is being instantiated at some later time in the launch process, I'll mark it correct instead of Stephen's. Thanks Stephen!
The "easy" solution would be to have managedObjectContext create a MOC if one doesn't exist (i.e., change it from a property to a method). That way which ever code gets there first the stack will be available.
(I'll spare the lectures about both creating the Core Data stack in the app delegate and accessing the app delegate like that!)
Here's another option without having to subclass NSApplication:
Don't put your view controllers in the .xib that you set as the Main Interface, just have the Main Menu (menu bar), AppDelegate and Font Manager in there.
Then make your view controllers in other .xibs.
Then in the applicationDidFinishLaunching method init your view controllers from their .xib files.
I also faced this issue with setting up Parse. To get around it, I simply subclassed NSApplication and set it as the Principle class in the Info.plist. In your NSApplication subclass, override the init methods and initialise Parse or anything else you need to, there.

Could not connect the action : to target of class NSApplication

I come from a Cocoa touch background and there's one point I'm stuck on, I'm trying to create a ViewController from scratch and connect objects in my xib to actions in my new ViewController. I changed the file's owner to my ViewController and added outlets, and the compiler seems to be happy with what I've done.
But when I run my application, the connections seem to fail with: 'Could not connect the action start: to target of class NSApplication,' but where is this NSApplication reference hiding? To the best of my knowledge my ViewController has a class of NSViewController.
ViewController : NSViewController
I changed the file's owner to my ViewController and added outlets, and the compiler seems to be happy with what I've done.
Sure, the compiler won't care -- this is a run-time error. It sounds like you're working in your MainMenu.xib file. That file is loaded by the application object. Even though you changed the type of File's Owner in the .xib, the object that's loading the .xib is still the application.
You'll probably want to create a separate .xib file for your view controller to load. You change the type of File's Owner in that file to you view controller class! hook things up to File's Owner, and it should work fine since your view controller really will be the object that's loading the file.

What is the need of File's owner in xcode xib files? Can i do the same things without file's owner?

Why should I set File's Owner's Class Identity rather than the Class Identity of my custom object that is shown in the nib and make the connections from it? What happens if I set file's owner to nil?
To me everything works fine with nil file's owner so what is the deference in doing the connection from it?
A NIB represents an archived object graph. You can load it and that object graph will be reconstituted. The thing, you usually want/need the newly-loaded object graph to be hooked into the already-existing object graph of your program. You don't want it to be standing apart, disconnected from everything else.
There are a few ways that the newly-loaded object graph can get connected to the rest of the program's object graph. One way is the set of proxy objects available in a NIB. There's one for the application object. Another such proxy object is File's Owner. A proxy object is a thing which has a representation in the NIB but is not actually contained in the NIB. Unlike the other objects in the NIB, the objects represented by the proxies are not created when the NIB is loaded, they exist before the NIB is loaded. The proxies allow connections between these pre-existing objects and the objects in the NIB. That's how the new object graph from the NIB can be connected to the existing object graph of your program.
The MainMenu NIB is unusual. It is automatically loaded at application startup by Cocoa, which means there isn't (can't be, really) much in the way of pre-existing objects. That NIB also usually contains an instance of the app delegate, which is a kind of coordinating controller. Usually, though, other types of NIBs would not contain coordinating controllers. (They do contain mediating controllers, like NSArrayController, but that's different.) Rather, coordinating controllers are typically created in code and, often, they are responsible for loading NIBs.
For example, you would use an NSWindowController as the coordinating controller for a window. The window would be defined in a NIB. The window controller would be instantiated in code – whichever code decides that a window should be created – and it would load the NIB. It would be the File's Owner of the NIB, too. It would manage the window and the top-level objects of the NIB.
If you are setting the File's Owner to nil, then a) you probably are dealing with very simple NIBs at this point, and b) you may be leaking top-level objects from the NIBs that you load.
File's owner is the file that contains all the IBOutlets and IBActions for that view. For example, if you have a class "ViewController" and it contains an IBOutlet UIButton *button and -(IBAction)changeViewWhenButtonPressed: (id) sender, the only way you can connect the outlet and action is through setting "ViewController" as your view's File's Owner.
I am relatively certain that Class Identity is synonymous with File's Owner.
Also, these links might be helpful:
What are File Owner and First Responder in iPhone SDK - xCode?
File's Owner Definitions
What is File's Owner
The “file's owner” is the way that objects in the nib can refer to objects outside the nib, and vise versa. (There are also some more complex ways to do that, but they're not used as often.) If you don't need to do that, you don't need to use file's owner.
For the main app, the file's owner is the Application object. You might not have a need to make connections to it, if all your application logic is in a custom class also instantiated in the nib and if you use “first responder” for action messages sent to the application. This is OK.
If you have a document window or popover or something, frequently the file's owner is the object being viewed, and so it's useful to be able to attach ui to it. You might load the same nib many times, each 'owned' by a different instance of that class — a different document or inspected-object or something.
(Fundamentally, the file's owner is just whatever object was passed to the "owner:" parameter in the nib-loading method.)

How to hookup a MainWindow.xib to an empty project

Beginning with XCode 4.2, when you create an empty project using XCode 4.2, a MainWindow.xib is no longer created and hooked up for you. I've found an article that describes how to do this and I've done it and it works, but if this process has taught me anything, it has shown me that I have no idea how main(), AppDelegate and the MainWindow.xib exist together.
http://www.trappers.tk/site/2011/06/16/mainwindow-xib/
Why is MainWindow.xib class updated to UIApplication?
Why is an object placed on the xib, and then AppDelegate class is selected for the class?
Why is the delegate outlet of the File Owner connected the AppDelegate object?
Why is the the window outlet of the AppDelegate to the Window?
why does - (BOOL) application:didFinishLaunchingWithOptions: need to be commented out.
I've researched around but, I'm still not 100% sure how everything is loaded up once the application starts, and why this is setup is needed just to have a MainWindow. I have a feeling though that I should probably get all these concepts down to continue to advance in iOS development.
Why is MainWindow.xib class updated to UIApplication?
At the lowest level, nib files are loaded with the method -[UINib instantiateWithOwner:options:]. The File's Owner in a nib file is a placeholder. In Xcode, it isn't a specific object yet. It will resolve to an actual object when the nib file is loaded. Its purpose is to relate, via outlets and actions, objects inside of the nib with the object that loaded the nib. The object passed as the "instantiateWithOwner:" parameter of that UINib method is what the File's Owner placeholder in Interface Builder will resolve to.
UIApplication loads the nib file specified in the info.plist and passes 'self' for the owner parameter when loading the nib file.
By setting the class name, you're just hinting to the tools so that they can suggest the set of actions and outlets you're allowed to establish.
Why is an object placed on the xib, and then AppDelegate class is selected for the class?
When you place the generic object in the xib and change its class to 'AppDelegate' you're telling Xcode to instantiate an instance of 'AppDelegate' when the file is loaded.
Why is the delegate outlet of the File Owner connected the AppDelegate object?
UIApplication has a 'delegate' that it delegates responsibility to and notifies when interesting events occur. When you make this connection, you're setting the delegate property of the application to be the instance that you specified above. From that point on, this instance will receive the delegate messages from UIApplication, like -application:didFinishLaunchingWithOptions:.
Why is the the window outlet of the AppDelegate to the Window?
Outlets are a way to refer to objects inside of a xib. They cause properties or instance variables to be set to refer to the object pointed to by the outlet. When you make this outlet, you're making it so that the app delegate instance you created above has a way to refer to the window that's also created when the xib is loaded.
why does - (BOOL) application:didFinishLaunchingWithOptions: need to be commented out.
It represents the code-focused way to do some of the same things that are happening in the xib, and if they were both present, they would be overwriting each other.
The object placed on the XIB file is the AppDelegate because it delegates all connections in the Interface Builder, meaning if you write a method that when a button is clicked it displays text, that method would be connected to either the App Delegate or the File's Owner, preferably the delegate. The File's Owner, since it is the UIApplication, connects to the delegate because it assigns that certain object to be the App Delegate. Sorry that I couldn't answer the rest of your questions, they didn't really make sense.
Hope this helps

What describes the "File's Owner" best in objective-c / cocoa Nib?

Unfortunately, the explanation of File's Owner is pretty short at the Apple docs. I know it is an proxy object. But what's really the point about that "File's Owner" object? What is it good for?
Nib files are often referred to as "freeze dried" and ready to run, and they are a great way of making your apps more modular which can reduce memory usage. Nib files can be defrosted, or loaded into memory anytime when the app needs the objects inside it.
Whenever a nib file is defrosted, it needs a pointer to the object that defrosted it. And that object is usually, the File's owner. The File's owner allows objects inside the nib file to access objects that existed before the nib file was defrosted. In a way, the File's owner acts as a bridge between newly loaded objects and old objects.
It's easier to understand the meaning of the File's Owner reference if you read about and understand the nib loading process.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html
Cocoa's frameworks handle many nib loads automatically on your behalf, with one of Cocoa's own built-in classes serving as the controller class that manages, or "owns" the nib file's instantiated objects. When you load your own nibs manually, you get to choose which class will serve as the file's owner.
When you read about the nib loading process, pay attention to the "owner:" parameter on many of the loading methods. Its exactly this object that will be connected to the objects in your nib file as File's Owner
I know it is an proxy object.
It's not. It's a real object. The icon in the nib is a proxy only in the sense that all the other icons represent objects archived in the nib, and the File's Owner isn't. But the FO is not a proxy object in your application.
But what's really the point about that "File's Owner" object? What is it good for?
It's the object that owns the objects in the nib.
That's it. Nothing more to it than that.
Best way to explain it is with an example of how to set it up. Let's say you have an NSWindowController subclass which is a controller for a preferences window. The preferences window is in a NIB called "Preferences".
In your NSWindowController subclass you would have the following init method:
- (id)init {
if (self = [super initWithWindowNibName:#"Preferences"]) {
//do initalisation
}
return self;
}
This initialises the window controller, associating it with the nib named "Preferences" in the application's main bundle. Note that the NIB has not yet been loaded (this will happen when you first call -window on the window controller.
In the Preferences NIB you would then click on the File's Owner icon and then go to the Class Info panel of the Inspector. In here you would set the class to the name of your window controller class (eg PreferencesController). This now represents an instance of your window controller so you can connect up outlets and actions.
While editing in IB it is just a proxy of the object, as with any object you drag to the NIB, but when the NIB is loaded it will be set to the window controller you created.
http://www.cocoadev.com/index.pl?FilesOwner
In essence, whichever object loaded the NibFile becomes the file's owner for that nib file.