small medium large xlarge

Back to: All Forums  Core Data
Generic-user-small
01 Aug 2009, 06:57
Felipe Laso (104 posts)

Hello.

I’m nearing the end of the first chapter. I built the application and it works properly. The one thing I don’t understand is this:

- (IBAction)addImage:(id)sender 
{ 
	id recipe = [[recipeArrayController selectedObjects] lastObject]; 
	
	if (!recipe) 
	{
		return; 
	}
	
	NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 
	
	[openPanel setCanChooseDirectories:NO]; 
	[openPanel setCanCreateDirectories:NO]; 
	[openPanel setAllowsMultipleSelection:NO]; 
	
	SEL select = @selector(addImageSheetDidEnd:returnCode:contextInfo:); 
	
	[openPanel beginSheetForDirectory:nil 
								 file:nil 
					   modalForWindow:window 
						modalDelegate:self 
					   didEndSelector:select 
						  contextInfo:recipe]; 
} 

When the “select” SEL is created and we specify it to be “addImageSheetDidEnd:returnCode:contextInfo:”, we never specify the objects to be passed into that selected. So when I read the definition for the “addImageSheetDidEnd:returnCode:contextInfo:” method…I was left baffling as to how it knows which NSOpenPanel, NSInteger and NSManagedObject we are talking about???

Shouldn’t those values be passed into the function at some point or is Cocoa and Objective-C so magical that it knows what to work with?

Thanks in advance, I have been working with Objective-C for quite a while but this doesn’t make sense. Specially not from a C++ background where every function that has parameters must have them passed into the function when being called.

Cheers, Felipe.

Generic-user-small
22 Aug 2009, 14:02
Matthew Whillock (8 posts)

Hi Felipe,

As far as I understand it there is a bit of compiler and run-time magic going on.

The method that SEL is pointing to must have a signature of the form:

-(void)foo:(NSWindow *)aWindow bar:(int)returnCode baz:(void *)contextInfo;

which keeps the compiler happy. Of course most people change the method name to something more sensible (addImageSheetDidEnd:returnCode:contextInfo for example). The NSWindow is instantiated at run-time to be the window you set in the openPanel call (window, in this case). The same goes for the contextInfo. The value for the returnCode is set automagically by the sheet when the sheet is dismissed by pressing the ok or cancel buttons.

The Xcode documentation viewer gives details for the beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo method.

Hope that helps.

Oh yes, try to forget everything about c++. :)

Flames welcome.

Cheers, Matt

Avatarsmall_pragsmall
25 Aug 2009, 16:35
Marcus S. Zarra (284 posts)

This is part of the power of Objective-C. We are effectively passing a pointer to the method that will be called after our asynchronous panel is finished. What this is doing under the hood is creating a @NSInvocation@ which can determine how many parameters are in the message/method and it expects them to be in a specific (and fairly standard) order. It then populates the parameters based on its expected order. If we remove the last section of the method call then it will only populate the first two, etc.

It is a very powerful and useful feature. I recommend learning more about @NSInvocation@ so that you can use them in your own code.

You must be logged in to comment