For a Mac graphics application (not iPhone), I need something like a main method in Java, the first method that gets a program going. I've been looking at things like NSViewController and NSWindow object. I've looked around but can't find an answer to this seemingly easy question anywhere. (I am very new at this by the way)
Thanks
If you create a Cocoa project from one of the Xcode "Cocoa Application" templates, you'll get a main.m file that includes the usual startup code.
Try working through one of the tutorial projects that you'll find in the documentation.
If you are using the project templates, the startup code is in the ApplicationDelegate file. The main.m, for a Cocoa application, sets up the run loop, runs NSApplication (as you can see in the Info.plist file under the 'Principle class' key.
This then loads the nib file that is specified in the Info.plist file (under the 'Main nib file base name' key). The default is MainMenu.xib. Now have a look at this nib file.
This is already set up by the template to have a 'Files's Owner' of NSApplication (the class that loaded the nib) But There is also a blue block which represents the application delegate. This is already filled out with one delegate method one outlet.
The delegate method is applicationDidFinishLaunching: This method is called by the application. This is only one of the possible delegate methods that it can handle, but it is sent after the run loop is started but before the application receives any events. It is the common place to put your initialisation code. It is in here that you should start to set up your window, which you can get to using the pre-supplied window outlet.
This is just a quick summary. A handy referenece is on Cocoa With Love and Apple's Introduction to Application Architecture document.
Related
I have studying how to use IKImageView in my app. I downloaded the following demo from Apple site.
https://developer.apple.com/library/mac/samplecode/IKImageViewDemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004049
One thing I do not understand is: This project has only implemented a Controller class.
#interface Controller : NSObject
{
...
I do not understand how does it work at all. If I create a new project in XCode, it will usually generate an AppDelegate class which implements NSApplicationDelegate interface.
I do not know if I understand the mechanism correctly.
Does the following steps describe how it works?
1) In info.plist it specifies the main bundle is MainMenu.xib.
2) the Window is binded to the Controller like so
3) When the application starts, it loads the Windows from the MainMenu.xib and the Controller class takes over the windows interaction from there.
It's really old sample code. It predates Xcode project templates generating an app delegate for you.
Back then, early Xcode and ProjectBuilder (the old name for it)
Left it up to you to do that.
Lots of older sample code has this sort of thing. As long as things get kickstarted by nib loading, magic happens, objects are instantiated and connected
If you have a simple controller that inherits from NSObject and it has a proxy in you main nib file, it will get created. If you also connect its proxy as delegate to some view or control in the nib, all of that happens.
You don't technically need an object that is the delegate of you NSApplication object. But in reality it is a good best practice and any non trivial app will have that and a lot more.
There's a lot of magic that happens when the C function NSApplicationMain() is called at the launch of your app.
The old and in many ways out if date book Cocoa in a Nutshell covers this well.
Yeah you pretty much describe how it works and what it's doing.
It's relying on the fact that NSApplicationDelegate is an informal protocol and it doesn't declare that Controller conforms to it and is using the NIB to kick-start the app.
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.
It just sits there... How do I run code independently of UI actions (as in, not only in response to a button push)? I'm trying to initialize some objects and run some scripts BEFORE i awakeFromNib. How do I do this?
In Cocoa, what is the purpose of the main.m class?
None, because there isn't one.
For one thing, the .m file is not the class. Neither is the .h. The practice of putting a class's #interface in a .h (header) file and its #implementation in a .m (implementation) file is a convention, nothing more. It's a good convention, but it's not enforced by the language.
So, a .m file contains zero or more class implementations. Usually, it's exactly one. Sometimes it's two, where the other is a small private class whose #interface is also in the same file.
main.m contains no classes. It usually only contains one function, which is named main.
main comes from C (of which Objective-C is a superset), and is the entry point of the program: It's where the program starts running. Everything happens here, or in a function called from here. A command-line tool will usually exit here as well, by main returning.
Most main functions in Cocoa apps are the default one that comes with the project template; this implementation simply tail-calls NSApplicationMain, which sets up the shared NSApplication object and starts it running. That function never returns; when the user quits a Cocoa app, the process simply exits.
You may want to read this list of important facts about Cocoa and Objective-C that I wrote. It sounds like you have some misconceptions (probably brought over from another framework you're more familiar with) that that list can clear up for you.
How do I run code independently of UI actions (as in, not only in response to a button push)?
That depends on when you are trying to do it. A periodic action, for example, would be a job for a timer.
I'm trying to initialize some objects and run some scripts BEFORE i awakeFromNib. How do I do this?
You could do it in initWithCoder:, which is sent to every non-view-layer object instantiated from an archive, including yours. Nibs are archives, too.
You might also consider being the application delegate and implementing a applicationWillFinishLaunching: method.
A third way would be to stuff the code in main. Note that practically any Cocoa code here is likely to log “no autorelease pool” warnings unless you wrap it in an #autoreleasepool statement; other solutions don't have this problem because NSApplication has already created an autorelease pool for you.
main.m is what starts the application - to run things befor nibs load put it in main.m before the NSApplication is created.
I want to incorporate an applicationDidFinishLaunching: into my cocoa delegate. How would I do this?? On the iphone SDK the applicationDidFinishLaunching is already in the application delegate, but when making my mac application I noticed that there were none.
Best Regards,
Kevin
As of Xcode 3.2, the Mac application template also comes with an application delegate, already connected, that has such a method.
To set this up in a project created before Xcode 3.2, create a new class for your delegate to be an instance of. I usually name mine “AppDelegate”. You'll do this by right-clicking on the Classes group and choosing “Add File”, then picking the Cocoa NSObject Subclass file template.
Open the header you just created (AppDelegate.h). Give it any instance variables you want. Then hit Go to Counterpart. That takes you to the implementation file (AppDelegate.m). Add your applicationDidFinishLaunching: instance method here. Unlike on the iPhone, this is a notification-handler method, so it takes an NSNotification instance and not an NSApplication instance.
Now to hook it up. In the Resources group, open MainMenu.nib. Drag an Object from the Library window into the top-level nib window (the one with icons in it, such as File's Owner and First Responder). Select the object you just created and open the Identity inspector. Set the object's class to AppDelegate, matching the name you used in Xcode. Right-click on the File's Owner, and drag from its delegate outlet to your new object.
In Xcode, add an NSLog statement to your applicationDidFinishLaunching: method. Hit Save All, then Build and Go. Switch back to Xcode and open the Debugger Console. If you did everything right and I didn't forget anything, you should see the log message there.
- (id)init
{
if (self = super init]) {
[NSApp setDelegate:self];
}
return self;
}
You can also do this in Interface Builder; from "File's Owner" in MainMenu.xib, just drag the "delegate" outlet to your object. You may want to consider using -awakeFromNib instead though.
Were you missing the application delegate files altogether? It seems as though there's a bug in the Xcode installation scripts (at least for 3.2.1 on Snow Leopard) that installs the latest project templates in the wrong folder. The older template for a "Cocoa Application" project doesn't contain the delegate files.
I've explained what I've discovered (and how I "fixed" it) in a blog post called Fixing the Xcode Project Templates.
Cheers,
Graham
i am currently starting to learn Xcode and objective-c and i am reading three different books on that topic currently. All of these books refer to a file called "AppDelegate" (My_First_ProjectAppDelegate.m, My_First_ProjectAppDelegate.h) which are said to be "created with the Project" (i am creating a "Cocoa Application"). These files are not present when I create a new Project. I seem to be not the only one having this problem (see http://pragprog.com/titles/dscpq/errata ).
Is there any more information about AppDelegate? What is the current practice on how to deal with a missing Appdelegate? i am using Xcode Version 3.1.4 on Mac OSX Leopard.
AppDelegate is nothing more than a common NSObject class with needed connections in MainMenu.xib. You can easily recreate your own:
Create a class, name it AppDelegate
Open MainMenu.xib and add NSObject object to object palette
In object inspector's Identity tab (the last one) set object's class to AppDelegate (you should get autocomplete)
Ctrl+drag from Application object to your newly created AppDelegate object and choose "delegate" from opened panel.
As I recall, only the iPhone templates were providing delegate classes by default. This is not a huge deal, but I can see how you would be concerned if you are just learning. Are you sure what you are reading is relevant to MacOS applications and not Iphone?
You can always create your own delegate class manually. You just create a class as you normally do, then set it as the delegate for NSApplication in Interface Builder.
I think the confusion comes from the version of XCode you are using.
Xcode version 3.2 changed the default behavior when you create a new project: it now creates an AppDelegate for your project. I can't remember what the earlier versions did, but it was different.
As Eimantas says, if you want to use an AppDelegate then you can just create one following the steps he describes.