How should you use WebKit's WebView with a modal dialog?
[_webView setMainFrameURL:[NSString fromStdString:url]];
[_nsWindow makeKeyAndOrderFront:nil];
return [NSApp runModalForWindow:_nsWindow];
The preceeding code is only working on Mac OS 10.6. Using 10.5 this is not navigating to the specified URL. Witho开发者_如何转开发ut the runModalForWindow, everything is working.
WebView
only works on the main loop and thus doesn't cooperate in this case. One solution would be to run the modal session yourself and keep the main loop manually alive (similar to what is proposed here). E.g.:
NSModalSession session = [NSApp beginModalSessionForWindow:yourWindow];
int result = NSRunContinuesResponse;
// Loop until some result other than continues:
while (result == NSRunContinuesResponse)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Run the window modally until there are no events to process:
result = [NSApp runModalSession:session];
// Give the main loop some time:
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
// Drain pool to avoid memory getting clogged:
[pool drain];
}
[NSApp endModalSession:session];
Note that you probably want to use something like -runMode:beforeDate:
instead to keep the CPU load down.
I've been searching for solutions and now I can use WebView on modal session using following code. Without using -runMode:beforeDate
my WebView cannot process keyboard or mount events:
- (void) OpenURL:(const char *)_url
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
[NSApp setDelegate:self];
NSString *url = [NSString stringWithUTF8String:_url];
NSLog(@"OpenURL: %@", url);
NSRect windowRect = NSMakeRect(10.0f, 10.0f, 800.0f, 600.0f);
NSWindow *window = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:(NSResizableWindowMask|NSClosableWindowMask|NSTitledWindowMask)
backing:NSBackingStoreBuffered defer:NO];
[window setDelegate:self];
WebView *webview = [[WebView alloc] initWithFrame:windowRect
frameName:@"mainFrame"
groupName:nil];
[webview setFrameLoadDelegate:self];
[[webview mainFrame]
loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
[window setContentView:webview];
[window makeKeyAndOrderFront:nil];
// Modal Session
NSModalSession session = [NSApp beginModalSessionForWindow:window];
_result = NSModalResponseContinue;
while (_result == NSModalResponseContinue) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
_result = [NSApp runModalSession:session];
// The event loop is a runloop data source, so any ui event will
// wake up the source and make this method returns, and so
// you can block the run loop and tell him to wait that
// something append. [2]
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
[self doSomeWork];
[pool drain];
}
[NSApp endModalSession:session];
[pool release];
}
You need to call [NSApp stopModal]
, [NSApp abortModal]
or [NSApp stopModalWithCode:yourReturnCode]
somewhere like this:
- (void)windowWillClose:(NSNotification *)notification
{
NSLog(@"windowWillClose");
[NSApp stopModal];
}
Links:
- [1]:http://www.dejal.com/blog/2007/01/cocoa-topics-case-modal-webview
- [2]:http://lists.apple.com/archives/cocoa-dev/2008/Apr/msg02260.html
精彩评论