How do sheets call functions in objective-C?

Discussion in 'Mac Programming' started by wrayal, Aug 23, 2008.

  1. wrayal macrumors newbie

    Joined:
    Aug 23, 2008
    #1
    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
     
  2. philippott macrumors newbie

    Joined:
    Sep 17, 2007
    #2
  3. wrayal thread starter macrumors newbie

    Joined:
    Aug 23, 2008
    #3
    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)
     
  4. philippott macrumors newbie

    Joined:
    Sep 17, 2007
    #4
    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
     
  5. wrayal thread starter macrumors newbie

    Joined:
    Aug 23, 2008
    #5
    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.
     
  6. philippott macrumors newbie

    Joined:
    Sep 17, 2007
    #6
    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
     
  7. wrayal thread starter macrumors newbie

    Joined:
    Aug 23, 2008
    #7
    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.
     
  8. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #8
    What does the connectionTerminatedSheetDidEnd:returnCode:contextInfo: method look like? There's probably something else going on in there.
     
  9. wrayal thread starter macrumors newbie

    Joined:
    Aug 23, 2008
    #9
    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].
     
  10. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #10
    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];
     
  11. wrayal thread starter macrumors newbie

    Joined:
    Aug 23, 2008
    #11
    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
     

Share This Page