2

I'm trying to create a Cocoa application that displays SavePanel, and after user choose file, it prints it on stdout. I'm total beginer with Objective-C and Cocao. Problem is that it doesn't take keyboard input, it is only posible to choose file with mouse.

This is the code:

#import <Cocoa/Cocoa.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    NSSavePanel *sPanel = [NSSavePanel savePanel];
    int result = [sPanel runModal];
    if (result == NSOKButton) {
        NSString * filename = [sPanel filename];
        char * fileStr = [filename UTF8String];
        printf("%s\n", fileStr);
    }
    return 0;
}
John Smith
  • 21
  • 1
  • 1
    If the goal is to learn Cocoa, start with a Cocoa application. If the goal is to try and integrate actual UI with a shell script, turn the problem around and wrap the shell functionality in a real app. I've seen a lot of attempts at integrating UI with a command line based workflow and they have universally been awful. – bbum Apr 11 '12 at 16:54

1 Answers1

1

The AppKit/Cocoa classes require an NSApplication object to be initialized in order to handle user input (among other things). Adding this line to the top of your main function should do the trick:

int main(int argc, char *argv[])
{
    [NSApplication sharedApplication]; // ** Add this **

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSSavePanel *sPanel = [NSSavePanel savePanel];
    int result = [sPanel runModal];
    if (result == NSOKButton) {
        NSString * filename = [sPanel filename];
        const char * fileStr = [filename UTF8String];
        printf("%s\n", fileStr);
    }
    [pool drain];
    return 0;
}

More information about this can be found in the documentation for NSApplication, particularly these points:

Every application must have exactly one instance of NSApplication (or a subclass of NSApplication). Your program’s main() function should create this instance by invoking the sharedApplication class method.
NSApplication performs the important task of receiving events from the window server and distributing them to the proper NSResponder objects. NSApp translates an event into an NSEvent object, then forwards the NSEvent object to the affected NSWindow object.

Along the lines of bbum and danielpunkass's comments below, this isn't the way you'd really write a Cocoa application, and while it does make your immediate issue go away, it's not a complete or completely correct solution. To expand on Daniel's comment, and to get you started easily, create a new Cocoa application project. Open up the application delegate class (created for you), and put your code in the -applicationDidFinishLaunching: method. As implied by its name, that method is called after the application has finished launching, and everything is setup such that you can use the AppKit classes normally. As you gain more experience, you'll better understand the typical Cocoa application architecture and can move on to creating user interfaces, etc.

Andrew Madsen
  • 21,309
  • 5
  • 56
  • 97
  • 2
    This is on the right track, but it's not enough to simply have a top-level NSApplication established. You need to be running the application's main thread run loop for things to work as expected. In any case, efforts to "make this work" are the wrong tack. The questioner should be approaching their learning starting from a basic new "cocoa application" template in Xcode, focusing on the app delegate class for experimentation. – danielpunkass Apr 11 '12 at 15:15
  • This didn't seem like it should be a complete solution, but it does indeed work for this simple case, at least on my machine (10.7.3). That said, @bbum and danielpunkass are both more experienced and knowledgeable than I am, and know what they're talking about. – Andrew Madsen Apr 11 '12 at 15:21
  • I completely agree. To me it's interesting that this works, but in reality you'd never use this in a real application. I've edited my answer with more. – Andrew Madsen Apr 11 '12 at 15:31
  • But it doesn't. Keyboard input is still focused at terminal, and not in editbox. – John Smith Apr 11 '12 at 15:56
  • Yes, well, clicking on the save panel gives it focus, and you can type in the "editbox". But this is another hint at the fact that Cocoa programs aren't meant to be written this way. – Andrew Madsen Apr 11 '12 at 16:01
  • 1
    What @danielpunkass said (at a keyboard; not a tappy-tappy like my original very terse comment). The key point is that treating a Cocoa application like an extension of command line programming is a path to frustration. The OP should start with a real Cocoa program, understand how it works, then solve whatever problem they have. – bbum Apr 11 '12 at 16:52