tags:

views:

98

answers:

4

I'm trying to build a super-simple Cocoa app, basically one that has one function (for example, main()) with a while loop. It does some stuff, does a curl request, then waits a few seconds before starting over.

I've got my project all setup in XCode with all the necessary variables and functions, but I don't know where to put my main() function that does all the work.

Where do I define the main function?

+5  A: 

If you design your app according to the usual Cocoa architecture, you don't really put any of your own code in main. The whole app should be event driven (where events are things like UI interactions from the user, network events, etc).

That said, there is a main function. If you've created a default Cocoa project in XCode, the main function will be in a file called "main.m". It will get run just like a main function in C. You'll see that there's a call in there to NSApplicationMain(). That's what starts a Cocoa application running (creates the application, loads the main nib file, starts running the main run loop, etc) . NSApplicationMain() doesn't return until the application quits, so if you really want to put stuff in main(), you need to put it above the call to NSApplicationMain().

Again, that's not the normal "Cocoa way" to do things, but without more info about what you want to do, it's hard to give you more advice.

Andrew Madsen
Hm, that could be an issue because this isn't event driven. It works more in a headless manner, ie stuff happens whether or not the user does anything.
davethegr8
Not necessarily a problem. Consider implementing the applicationDidFinishLaunching method in your application's delegate class. This will "do stuff" when the rest of the framework is ready to go. http://stackoverflow.com/questions/245390/nsapplication-and-applicationdidfinishlaunching has some more info.
Joey Hagedorn
Yeah, starting things off in -applicationDidFinishLaunching is a valid way to go. I would add though that if you want any Cocoa UI at all and need it to work (even just a Quit menu item), you need to make sure that the main run loop gets run so that it can handle incoming events (see NSRunLoop documentation) . Otherwise your app will need a Force Quit to kill it.
Andrew Madsen
*grumble grumble* force kill... That's what I'm trying to get around. I've got an applescript app that does pretty much that. :(Basically, I'm just trying to curl a specific url with a few bits of data every 10 seconds or so.
davethegr8
davethegr8: If you want your app to respond to Quit events, then you need it to respond to events, at which point it becomes event-driven. Fortunately, this is not mutually exclusive with the timer solution (or with using NSURLDownload or NSURLConnection to do the downloading/data-retrieval).
Peter Hosey
+1  A: 

To add to Andrew Madsen's answer, the best thing to do is start with an Xcode project template. It'll get a skeletal main(), a XIB, a plist, and other standard Cocoa stuff set up for you.

Graham Perks
+7  A: 

Cocoa is very much oriented towards event-driven programming. That end, the main() function generally just starts up the main runloop and then the application delegate can kick off anything it wants to do. That said, it's certainly possible to write a non-event-based cocoa program that uses main() To do more complicated stuff. In that case, it works basically the same as in C.

Cocoa With Love just had a post about Minimalist Cocoa programming that may be of interest. It uses main() to do some work. It's not really something I would recommend emulating in your own app, but it's certainly possible.

Kevin Ballard
+3  A: 

As others have answered, it's possible to implement what you want to do in a way you suggested, i.e., by running a while loop inside main.

However, that is not the best way to write a Cocoa app which reloads a URL once in a few seconds. In a different environment, there's a different standard way to do things. So, you sometimes need to un-learn what you got used to. You might have thought: I want to do X. In language/environment A, I would have coded like P to do X. Now I'd like to use language/environment B. How should I implement P? That's not the way to get used to a new environment. Just ask, How should I do X in the environment B?

The most Cocoa-esque way would be this:

  1. Open XCode, create a new project, choose a Cocoa GUI app from the template.
  2. In the application delegate, implement applicationDidFinishLaunching:. We are going to set up an NSTimer.

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
          NSTimer*timer=[NSTimer scheduledTimerWithTimeInterval:5
                                                         target:self 
                                                       selector:@selector(timerFired:)
                                                       userInfo:nil
                                                        repeats:YES];
    }
    

    This creates a timer which fires once in five seconds, and at each time it fires it calls the method timerFired: of the app delegate itself, specified by self. For more on NSTimer, read this apple document.

  3. Implement timerFired:.

    - (void)timerFired:(NSTimer*)theTimer{
          // do whatever you want. you can use plain C to invoke curl, 
          // or if you want you can use Cocoa methods to access a URL.
    }
    
  4. There's no fourth step!

The main function is provided by the template. It calls NSApplicationMain, which set up the Cocoa system. Eventually, it calls applicationDidFinishLaunching: of your delegate for you. You respond to that message. Then you set up a timer. The timer calls the method you specified for you. Then you respond to that message, again. That's basically how Cocoa works. The Cocoa system asks you to do something, so you do something. Your control over the flow of the program becomes rather passive, compared to what you would have programmed in Applescript.

Yuji
See, this is why I love SO. A complete answer to a complicated question that I don't know how to ask properly, that gets me to where I need to be. You're absolutely correct about the changing environments thing as well, so thanks for giving me a good template to ask future questions.
davethegr8