In an Xxode project that has a lot of .h and .m files, how do you determine which file gets executed first?
The file that contains int main(int argc, char * argv[]); will get run first, since the main() function is the first function to get run. In pretty much every Xcode template project, that file is called "main.m".
edit
Usually, the main() function of a Cocoa Touch app is this:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
(Substitute NSApplicationMain() for UIApplicationMain() and remove the autorelease pool if you're writing a Mac app)
edit #2
I'm only interested in the file that gets run first from the classes folder
The simple answer is "The application delegate", then everything else.
The technical answer to that is that any objects in your MainMenu.xib (Mac) or MainWindow.xib (iOS) file will be instantiated first. Usually the objects in that file will be instantiated in the order in which they appear, but I don't think that's guaranteed.
So if you 3 have custom top-level objects in your MainWindow.xib file, then they'll all be instantiated at the same time (within reason). First their initWithCoder: methods will execute, then some time later their awakeFromNib methods will execute (which usually the safest "starting point" for that object).
The application delegate launch methods will happen somewhere along in there too (I believe in between initWithCoder: and awakeFromNib).
Cocoa and Cocoa-Touch apps are completely event-driven. It is not that the order the methods are executed can be understood by reading the source code files.
As Dave explained, the entry of the program is at the main function in main.m. It immediately calls UI/NSApplicationMain.
NS/UIApplicationMain is a function provided by Cocoa(-Touch). It watches the user interaction, and fires events accordingly.
For example, when the user clicks a button, the system calls automatically what you provided as the action method specified in the xib file.
Another example is the drawRect: method you provide: it's called when the system decides to draw an object onto the screen. It's very important that you don't actively draw to the screen. The system asks you to draw the screen, and you respond.
One important set of events are the ones which are called at the beginning of the program, like applicationDidFinishLaunching: or the ones which are called when a view is loaded from the xib file, viewDidLoad.
Aaron Hillegass made a great analogy of the situation: you're KITT and respond to Michael Knight's order, not the other way around. Well you need to be over certain age to understand this analogy...
Another thing that should get run first is in an App Delegate (Defined like so: NSObject <UIApplicationDelegate> and setup in the nib) the method applicationDidFinishLaunching
This is obviously not technically the first thing to be run. The main loop and whatever is in UIApplication will be executed first, but in general this is good starting point for iOS applications and the first place you really have control.
You can also create a class called like "Controller" and drag an NSObject into your nib and set the class to Controller. Then the method awakeFromNib will be called.
Either of these should be fine to set up your app.
Related
I'm looking at an Objective-C sample project at:
https://developer.apple.com/library/mac/samplecode/FunkyOverlayWindow/Introduction/Intro.html
I don't understand how main.m passes control to the other classes/objects.
Let me explain what I'm trying to do. I'm trying to build that app, step by step. My first step was to get main.m to compile. I believe this is the starting point for most applications. I don't know what to add/compile next, because main.m does't mention/refer to any of the classes in that project.
Any ideas?
The entry point in Objective-C programs is the function called main(). See the following code from main.m
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argue);
}
The main() function begins by calling a function named NSApplicationMain() that is cocoa framework function and not shown to user, which is functionally similar to the following:
void NSApplicationMain(int argc, char *argv[])
{
[NSApplication sharedApplication];
[NSBundle loadNibNamed:#"myMain" owner:NSApp];
[NSApp run];
}
Thus, [NSBundle loadNibNamed:#"myMain" owner:NSApp] is called by NSApplicationMain function and in this time, #"myMain" is identifier for Main Interface(as MainMenu.xib within sample source)
finally MainMenu.xib is run, and then OverlayWindow that is main window of MainMenu.xib will be run.
I appreciate, and understand perfectly, how you could not want to use Xcode - especially if, like me, you come from a Unix/GCC/Makefile environment. However, there are some things that are really quite hard to do without the Xcode GUI and linking buttons and widgets to your code is one of those things.
In Xcode, you click the button in your user interface and drag a line to the code attached to it - these are called IBOutlets and IBActions. So, my first suggestion is to Google those two terms.
Secondly, I recommend you watch this video on YouTube to understand what the XIB/NIB is and how to link it to your code and then you can try and do it without Xcode once you get the concept... video showing linking buttons to code.
I am sorry if this seems trivial, but I am sure its a reasonable question to ask here.
I worked a lot around the NSWindowController class, and it seems the only way to get it
to work fully (for my purpose), is by creating a new xib-file along with it.
My question is, would it be somehow feasible to work with MainMenu.xib and the NSWindowController class and an instantiated object controller, to get interaction with the windows' content. So far without xib the only code segments getting executed are within awakeFromNib. The purpose being, I want to save xib-file space, complexity and have it easily integrate with a bigger project. Just fyi this is not a document-based project.
Should I choose a different subclass of NSObject other than NSWindowController? Or is it not possible?
The code required to run for the class to be working fully is as follows:
- (void) tableViewSelectionDidChange:(NSNotification *)notification
{
NSInteger selectedRow = [logsTableView selectedRow];
if ([directoryList containsObject:[directoryList objectAtIndex:selectedRow]])
{
NSString *logContent = [NSString stringWithContentsOfFile:[directoryList objectAtIndex:selectedRow]
encoding:NSUTF8StringEncoding
error:NULL];
if (logContent != NULL)
{
[logsTextView setString:logContent];
} else
{
[logsTextView setString:#"No permission to read log"];
}
}
}
NSWindowController usually wants to create the window it controls, which means you either need to give it a XIB file that contains the window to create or override the various window creation methods to customize the window in code. So it's probably not feasible to use an already-instantiated window from a different XIB with your NSWindowController.
That said, I almost always create a a XIB and an NSWindowController subclass for every window in my apps. Even the preferences window gets its own window controller class. The only exception would be extremely simple windows, but even now I'm struggling to think of a good example.
Your method isn't being called because window controller instance isn't set as the table view's delegate. The typical pattern here is to create your window in a XIB, set your window controller as the custom class of the File's Owner object, and then hook up the table view's delegate and dataSource outlets to File's Owner. This makes your window controller the table view's data source and delegate, and the connections will be established automatically when the XIB is loaded.
I don't know if it's possible for me to include code here that's relevant as my project is so large but are there any typical reasons why NSLog would repeat some warnings and calls to it at occasions where only one call/error is occuring?
As an example, I have a subclass of NSBox that inits an instance of another class on awakeFromNib:
- (void) awakeFromNib {
burbControllerInstance = [[BurbController alloc] init];
if (burbControllerInstance) {
NSLog(#"init ok");
}
}
I get NSLog printing "init ok" twice. I don't see why this subclass would be 'awoken' twice anywhere in my project. This is part of a larger problem where I can't get variables to return anything but nil from the class I'm creating an instance of. I'm wondering if perhaps the double values are something to do with it.
This post could be helpful, i. e. one comment:
Also important: awakeFromNib can be
called multiple times on the
controller if you use the same
controller for several nibs – say,
you’re using the app delegate as the
owner of both the app’s About Box and
preferences dialog. So you’ll need an
extra guard test if you use
awakeFromNib for anything but
initializing the nib objects
Update: Much more interesting could also be this, where the author mentions that awakeFromNib gets called twice. Unfortunately there is no real answer for this particular problem but maybe some basic ideas.
Update #2: Another potential solution from stackoverflow.com: View Controller calls awakeFromNib twice.
The issue:
I have a UINavigationController as as subview of UIWindow, a rootViewController class and a custom MyViewController class. The following steps will get a Exc_Bad_Access, 100% reproducible.:
[myNaviationController pushViewController:myViewController_1stInstance animated:YES];
[myNaviationController pushViewController:myViewController_2ndInstance animated:YES];
Hit the left back tapBarItem twice (pop out two of the myViewController instances) to show the rootViewController.
After a painful 1/2 day of try and error, I finally figure out the answer but also raise a question.
The Solution: I declared many objects in the .m file as a lazy way of declaring private variables to avoid cluttering the .h file. For instance,
#impoart "MyViewController.h"
NSMutableString*variable1;
#implement ...
-(id)init
{
...
varialbe1=[[NSMutableString alloc] init];
...
}
-(void)dealloc
{
[variable1 release];
}
For some reasons, the iphone OS may loose track of these "lazy private" variables memory allocation when myViewController_1stInstance's view is unloaded (but still in the navigation controller's stacks) after loading the view of myViewController_2ndInstance. The first time to tap the back tapBarItem is ok since myViewController_2ndInstance'view is still loaded. But the 2nd tap on the back tapBarItem gave me hell because it tried to dealloc the 1st instance. It called [variable release] resulted in Exc_Bad_Access because it pointed randomly (loose pointer).
To fix this problem is simple, declare variable1 as a #private in the .h file.
Here is my Question:
I have been using the "lazy private" variables for quite some time without any issues until they are involved in UINavigationController. Is this a bug in iPhone OS? Or there is a fundamental misunderstanding on my part about Objective C?
It might be related to both instances of your view controller using the same statically-allocated variable.
In other words, both myViewController_1stInstance and myViewController_2ndInstance are using the same variable1 location in memory and overwriting one another.
Variables declared inside of the curly braces after your #interface definition have a memory location allocated by the runtime for each instance of the class (every time you call [<ClassName> alloc]. Variables declared in the global scope (that is, outside of any functions or class declarations) are just that: global. That means that the variable can only hold one value per running copy of your application.
There are no truly private variables in Objective-C, but you can hide them from other instances at compile time as described here.
A bit of a late reaction, but I've seen this problem before. Don't push two viewControllers animated at the same time. Push the first one without animation and push the second one with animation. UINavigationController can't handle two animations at the same time.
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.