Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
As it should Xcode sets up the main function in main.m as follows:

Code:
int main(int argc, char *argv[])
{
	return NSApplicationMain(argc,  (const char **) argv);
}

Perhaps this is a stupid question but the answer is really not obvious to me. How do I get the values in argc and argv from within my classes?

argc should be 1, at least, and argv[0] should be the parth to my program. And within main in main.m that is easily verified. But how do I read them later?

Also, how do I define a method that runs when the program starts? I can press a button and make a method do something, but how can I get a method to run without having the user do anything to create an event?
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
Also, how do I define a method that runs when the program starts? I can press a button and make a method do something, but how can I get a method to run without having the user do anything to create an event?

You can put it in an init or an awakeFromNib method.
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
Any idea for the argc and argv parameter problem? What happened to them when in "return NSApplicationMain(argc, (const char **) argv);"?


It is used in Command Line applications, which accept arguments from the command line, and it is used in C which Obj-C is based on, which I guess is why they are there. If you make a command line App in Obj-C you modify main.m so can use them...
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
It is used in Command Line applications, which accept arguments from the command line, and it is used in C which Obj-C is based on, which I guess is why they are there. If you make a command line App in Obj-C you modify main.m so can use them...

Yes, but how do I use them?

The first parameter contains the path to my binary, which is useful. The second should contain the path to the file (associated with my program) I double-clicked.
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
Yes, but how do I use them?

The first parameter contains the path to my binary, which is useful. The second should contain the path to the file (associated with my program) I double-clicked.

No idea, can't you get these values in a different way?
 

wittegijt

macrumors member
Feb 18, 2007
31
0
Eindhoven
If you know which command line options you want (e.g.: appname -path pathname), the easiest way is:
NSString *path = [[NSUserDefaults standardUserDefaults] stringForKey:mad:"path"];

If not, use the -(NSArray *)arguments method from NSProcessInfo.

Wittegijt.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
If you know which command line options you want (e.g.: appname -path pathname), the easiest way is:
NSString *path = [[NSUserDefaults standardUserDefaults] stringForKey:mad:"path"];

If not, use the -(NSArray *)arguments method from NSProcessInfo.

Wittegijt.


This is weird.

The first parameter is indeed the path to my binary. But the second parameter is not the file I double-clicked on. Instead I get the following:

"-psn_0_336986113"

When I do a "myprogram file.ext" in the command line I get the following two command line parameters:

1. path to my binary
2. "file.ext"

When I double-click on file.ext in the Finder (.ext files are associated with myprogram) I get the following two command line parameters:

1. path to my binary (as expected)
2. "-psn_0_336986113" (or some other number)

The second I did not expect. How do I get the path to the file I double-clicked? How does that work in Cocoa?
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
If you know which command line options you want (e.g.: appname -path pathname), the easiest way is:
NSString *path = [[NSUserDefaults standardUserDefaults] stringForKey:mad:"path"];

If not, use the -(NSArray *)arguments method from NSProcessInfo.

Wittegijt.

I got my program to display everything it could read in [NSUserDefaults standardUserDefaults] but the path to the file I double-clicked to open was not in it.

If the path to my file is not the second command line parameter or in the defaults, where is it?

I tried finding out in the TextEdit example source but it was too well-hidden.

This is surprisingly complicated and the documentation does not even touch the subject. Yet all Cocoa applications out there can open files double-clicked in the Finder if associated with them.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
The filename is not on the command line. When your application is running your NSApplication delegate (if you have one) will be asked to open any files double clicked on via:

Code:
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename

Note that this can get called over and over if you have multiple files to open. If you are using the document architecture this all get's handled automatically for you. If you are writing an application that can open documents you should probably be using the Document Based Application template in XCode.

You can see the description for this in the Delegate Methods section of the NSApplication documentation.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
The filename is not on the command line. When your application is running your NSApplication delegate (if you have one) will be asked to open any files double clicked on via:

Code:
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename

This sounds a lot more difficult than on other platforms. :-(

That means my application has to consider two different possibilities regarding the file it is supposed to open. One for having been started from a command line and one for the Finder.

I'll try the above.

Thanks.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
You can see the description for this in the Delegate Methods section of the NSApplication documentation.

The documentation keeps referring to "delegates" as if everybody is supposed to know what they are. :-(

Also, openFile does not seem to return a string.

This really is surprisingly complicated. Usually (on Windows and UNIX) the path to the file double-clicked can be found in the second command line parameter. What does my program need to be told its process number for?

Thanks for your help, but somehow I am unable to make the step from

Code:
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename

to getting the path for my file that I expected to find in argv[1].

In fact, none of the methods in NSApplication seem to return a string.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
delegation is a standard design pattern. It's not even really a Cocoa specific thing: .Net uses then a lot too, so yes you are supposed to know what they are. You keep referring to other platforms. Cocoa is not supposed to be cross platform. It's for writing Mac applications. If you want to write something cross platform it's probably easier to write a standard POSIX (or whatever) command line app and the wrap a true Cocoa GUI round it.

Anyway back on topic! Apple provide an amazing amount of very good documentation. Have you tried reading it? For example they explain delegates here. If you've not read the entire Cocoa Fundamentals guide then do that now. That's not a Aprils fool joke: it's well after midday here.

The basic idea is that you create a custom object and set that as the application delegate. In that object you implement a method with the signature I provided previously. NSApplication will then automatically call your method passing the filename as the named arguement.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
delegation is a standard design pattern. It's not even really a Cocoa specific thing: .Net uses then a lot too, so yes you are supposed to know what they are. You keep referring to other platforms. Cocoa is not supposed to be cross platform. It's for writing Mac applications. If you want to write something cross platform it's probably easier to write a standard POSIX (or whatever) command line app and the wrap a true Cocoa GUI round it.

Anyway back on topic! Apple provide an amazing amount of very good documentation. Have you tried reading it? For example they explain delegates here. If you've not read the entire Cocoa Fundamentals guide then do that now. That's not a Aprils fool joke: it's well after midday here.

The basic idea is that you create a custom object and set that as the application delegate. In that object you implement a method with the signature I provided previously. NSApplication will then automatically call your method passing the filename as the named arguement.

Wow!

How did you know that I never tried reading the documentation I was referring to? And how did you so clearly deduce that when I compared Cocoa to other platforms I was obviously referring to cross-platform development?


I have to thank the other two guys for helping me with the command line problem. It's good to see that people often explain something in simple terms rather than demonstrate how much more they know about the issue as such.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
I didn't say you hadn't read it. I asked if you had. You may have considered it to be a rhetorical question but it was not intended as one.

I simply thought that as you were asking a basic question about a core Cocoa concept that you might find some advantage in taking some time to read or re-read the basic core Cocoa conceptual documentation that is essential to understanding Cocoa.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
I didn't say you hadn't read it. I asked if you had. You may have considered it to be a rhetorical question but it was not intended as one.

I simply thought that as you were asking a basic question about a core Cocoa concept that you might find some advantage in taking some time to read or re-read the basic core Cocoa conceptual documentation that is essential to understanding Cocoa.

Ok. No harm, no foul; I am sure.

But seriously, I don't want to open the file, I only want to find out the path to it. Surely there must be an easier method like on other platforms?

Also, I'm not sure I have asked a question about a core Cocoa concept. The concept I am looking for is fairly universal and it works the same way on Windows and UNIX. I don't think it can be so much more complicated on a Mac, no?
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
It would be the same if you wrote a pure C command line app. Once you decide to use Cocoa you are deciding to use that Framework and all that brings. You don't have to open the file. Just return NO from the delegate method.
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
It would be the same if you wrote a pure C command line app. Once you decide to use Cocoa you are deciding to use that Framework and all that brings. You don't have to open the file. Just return NO from the delegate method.

So there really is no simple way to find out the path to the file double-clicked?
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
I really don't see what is so difficult about doing it via the delegate. See the absolutely minimal example attached. This is a non-document based app that "opens" files *.test. If you drop any .test file on it's Dock icon or (once you've run the app once) double click in any .test file it'll tell you the path.

Edit: forgot to attach file :eek:
 

Attachments

  • PathTest.zip
    31.9 KB · Views: 151

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
I really don't see what is so difficult about doing it via the delegate. See the absolutely minimal example attached. This is a non-document based app that "opens" files *.test. If you drop any .test file on it's Dock icon or (once you've run the app once) double click in any .test file it'll tell you the path.

Thanks!

Weirdly enough it works on its own. But when I add the method to my program with the only change of the name of the text field, it doesn't do anything.

Since other methods can update the text field in question I assume the text field works. But

Code:
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename

seems never to be called.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Did you check out the nib file? You need to ensure that there is an instance of the new class created somewhere (I did it in the nib) and that the instance is set as the NSApplication delegate (again I did it in the nib)...
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
Did you check out the nib file? You need to ensure that there is an instance of the new class created somewhere (I did it in the nib) and that the instance is set as the NSApplication delegate (again I did it in the nib)...

In your nib file I find an instance of the class AppDelegate. In my nib file is an instance of my class.

Does the class have to be called "AppDelegate"? I tried that, created the class, the files, and the instance in Interface Builder, but it still didn't do anything.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
The name is irrelevant. It obviously has to be an instance of the correct class (but the name is just a name). It then has to be connected as the NSApplication delegate. The FileOwner icon is the NSApplication (in this case, this is not always true). Do the normal to connect it as a delegate (ctrl-drag from FileOwner to the instance and choose delegate).

Edit it add: in case the start of that is not clear: the class can be called anything you like. The instance can also be renamed in Interface Builder without altering the class (in case you have two instances of the same class and you want to be able to tell them apart for instance).
 

ajbrehm

macrumors 6502
Original poster
Aug 14, 2002
341
0
Zurich, Switzerland
The name is irrelevant. It obviously has to be an instance of the correct class (but the name is just a name). It then has to be connected as the NSApplication delegate. The FileOwner icon is the NSApplication (in this case, this is not always true). Do the normal to connect it as a delegate (ctrl-drag from FileOwner to the instance and choose delegate).

Edit it add: in case the start of that is not clear: the class can be called anything you like. The instance can also be renamed in Interface Builder without altering the class (in case you have two instances of the same class and you want to be able to tell them apart for instance).

That worked! Thanks.

It's not obvious.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Well you don't have to do it that way. You could have your instance set itself as the application delegate programatically when it wakes from the bib. Or do you mean the way you do the connection? As that's covered in the tutorials. You eventually think it's second nature!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.