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

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
I'm working on modifying an existing open source objective C program (CotVNC) and it has the following line:

NSBeginAlertSheet(header, okayButton, [server_ doYouSupport:CONNECT] ? reconnectButton : nil, nil, window, self, @selector(connectionTerminatedSheetDidEnd:returnCode:contextInfo:), nil, nil, aReason);

The net result of which is, if you click ok, it calls connectionTerminatedSheetDidEnd with the default return code. This function then calls

[self connectionHasTerminated]

in the situation I'm using it, without doing anything else. I want to take out the sheet and have the function called directly, but for some reason, whilst with a button it works perfectly, replacing the NSBeginAlertSheet with simply

[self connectionHasTerminated]

or even calling connectionTerminatedSheetDidEnd with the appropriate arguments fails. So I assume that sheets must do something odd when they call a function. Do they perhaps spawn a new thread or something, or am I missing the point completely?

Thank you so much for any help!

Wrayal
 

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
Hi!

Thanks for the reply. The NSBeginAlertSheet actually works (the final call is optional, and nil works as well as NULL, though I will change it for correctness, thanks!). What I mean is, NSBeginAlertSheet _does_ work, but

[self connectionHasTerminated]

does _not_, even though they should be doing the same thing.

(connectionTerminatedSheetDidEnd just calls connectionHasTerminated in this case)
 

philippott

macrumors newbie
Sep 17, 2007
18
0
Hi!

Well it certainly has nothing to do with threads or the like, but rather how events are processed and in which order.

Docs say the modal session of the NSAlertSheet is over when it calls the supplied method but the sheet is still visible and needs to be "drawn out" yet. This means your connectionHasTerminated should not do anything to the window yet as there will still be some drawing actions from the retreating sheet neccessary.

Did you try recoding your NSBeginAlertSheet call exactly like the Apple sample?

Also the connectionTerminatedSheetDidEnd should look and work like in the example, that is if the returnCode == NSAlertDefaultReturn just then to call connectionHasTerminated.

I dont have a mac@hand so can only theorize :)

Regards
 

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
Thanks, but I say again, NSBeginAlertSheet _works_ (even when recoded as the apple example).

That is exactly how connectionTerminatedSheetDidEnd is coded, and it works. But I cannot get it to work _without_ a sheet: [self connectionHasTerminated] fails. I assumed, yes, because of event order. But I do not see how to make it execute in the same order _without_ a sheet.
 

philippott

macrumors newbie
Sep 17, 2007
18
0
Hi!

Oops, then is me who is missing the point here :)

Well, without further knowledge of how method connectionHasTerminated looks like or what it does it is hard to figure this out.

Seems to be an event callback function, meaning one that gets called from the main event loop. If you call this directly from code without an actual event then depending on its implementation it might work or not.

Same in the AppKit, you dont call windowDidClose directly in code, this is being called by the framework in response to a window close event. To close the window by code you call close or performclose.

Regards
 

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
Thanks again. Indeed, I had surmised much the same as you. The relevant code:

Code:
- (void)connectionHasTerminated
{
	[manager removeConnection:self];

	[socketHandler release];	socketHandler = nil;
	[_eventFilter release];		_eventFilter = nil;
	[titleString release];		titleString = nil;
	[manager release];			manager = nil;
	[versionReader release];	versionReader = nil;
	[handshaker release];		handshaker = nil;
	[(id)server_ release];		server_ = nil;
	[serverVersion release];	serverVersion = nil;
	[rfbProtocol release];		rfbProtocol = nil;
	[frameBuffer release];		frameBuffer = nil;
	[_profile release];			_profile = nil;
	[host release];				host = nil;
	[realDisplayName release];	realDisplayName = nil;
}

I'm hunting around as well. Thanks for the help.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
What does the connectionTerminatedSheetDidEnd:returnCode:contextInfo: method look like? There's probably something else going on in there.
 

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
I know, you'd expect so but...

Code:
- (void)connectionTerminatedSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
	/* One might reasonably argue that this should be handled by the connection manager. */
	switch (returnCode) {
		case NSAlertDefaultReturn:
			break;
		case NSAlertAlternateReturn:
			[_owner createConnectionWithServer:server_ profile:_profile owner:_owner];
			break;
		default:
			NSLog(@"Unknown alert returnvalue: %d", returnCode);
	}
	[self connectionHasTerminated];
}

The okay button passes NSAlertDefaultReturn so it breaks the switch, and runs [self connectionHasTerminated].
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
If it works 100% every time with the sheet then you could try this:
Code:
[self performSelector:@selector(connectionHasTerminated) withObject:nil afterDelay:0.0];
instead of
Code:
[self connectionHasTerminated];
 

wrayal

macrumors newbie
Original poster
Aug 23, 2008
9
0
Kainjow, it worked perfectly, thank you! I had tried a similar approach using performSelector but must have made a mistake. Thanks again :) I feel somewhat foolish now
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.