I'm trying to get WebKit to display the page title of the currently opened document window, which includes a WebView. The document won't display after I run the app.
I'm using Document.m and windowNibName to achieve this, but I'm sure what I'm doing is wrong. I think it might be with both the NSStrings, which I can't have. Though if I don't have them I can't return the Document title... (WebKit/WebKit.h is imported)
- (NSString)windowNibName:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
{
// Report feedback only for the main frame.
if (frame == [sender mainFrame]){
[[sender window] setTitle:title];
}
return #"Document";
}
You've implemented a method named windowNibName:didReceiveTitle:forFrame:, but nothing sends such a message (unless you are, but if you are, you left that code out).
The correct method name is webView:didReceiveTitle:forFrame:. Assuming you only have one web view in the window and only one window in the document, and assuming that the document is the web view's delegate, you can simply set the document's display name from there.
If you have something more complex going on, with multiple web views per window and/or multiple windows per document, then you'll need to ask the web view for its window, the window for its window controller, and the window controller for its document, and then set the document's display name as above.
Also, windowNibName has nothing to do with setting the document's title to the web page's title. The web view probably hasn't even started to load a page yet, if it even has a URL to load at all. That's why you need to be the web view's delegate and respond to that delegate message.
Related
I am having an issue similiar to this SO question. I would like to have a webview in an NSSheet in which I am doing some authentication to retrieve an API token.
I created a new NSWindowController subclass with a corresponding xib file. This is how I am starting the NSSheet:
- (IBAction)startAuthentication:(NSButton *)sender {
self.authController = [[AuthenticationWindowController alloc] initWithWindowNibName:#"AuthenticationWindow"];
[[NSApplication sharedApplication] beginSheet:self.authController.window
modalForWindow:[self.exportManager window]
modalDelegate:self
didEndSelector:#selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
}
In the windowDidLoad callback of this authenticationWindowController I am directing the webview to the URL:
- (void)windowDidLoad
{
[super windowDidLoad];
[[self.webView mainFrame]loadRequest:[NSURLRequest requestWithURL:authURL]];
}
It looks great at first sight: if I press the button, the startAuthentication action method is called and the new window is animated into the parent window and the authURL is loaded. The website is displayed correctly with its HTML form containing two input fields (username and password).
The problem is, that I can click on the page and it works, however if I am trying to click into one textfield, so that this field gets focus it does not work. No cursor appears in the text field of the website's form and after each keystroke I hear the NSBeep() sound.
I did some research on this topic and I found two references:
How do I use a WebView in a modal dialog?
Cocoa topics: the case of the modal WebView
What kind of puzzles me is that there is the Facebook Exporter for Aperture Plugin, which shows exactly what I want: a webview in a modal sheet. However I cannot find out what they are making differently . In the Facebook Exporter I have not found any code interacting with the run loops directly.
My questions
Is this a known problem with webviews in modal sheets?
Are the problems explained in the two references still there?
How can I get this working? I do not understand when to switch the runloop mode for example.
there is no general problem with this and I just tried it out again. must be some code besides this? can you narrow it down to the sheet? btw: my sample:
https://dl.dropbox.com/u/3753090/test2.zip
BUT all that said, modal runmode and webviews / timers / networking isnt very waterproof :)
because: when you go modal via one of the convenience methods in NSApp, the runloop is only run in a very limited way. :/
Currently, I have the following situation: I have a nib file that opens a menu, and has a unique main window. When this NIB-created view finishes the startup, the window is already initialized and displayed.
Besides starting the application with its normal way, I also want to start it in a particular way in which the window nor the menu are displayed.
I other words, I need to be able to define a condition at the startup of my application and based on that condition, I want to open/initialize/display the app using the normal view/nib or I want not to display them (but I may need to create/initialize the view).
Any ideas how can I do this?
Thanks
in the IB, go into the inspector and turn off 'visible at launch' for the main window.
THEN in your AppDelegate, check what to do: show the main window or make let it remain invisible and show the special window!
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
if (myCondition == TRUE) {
//do something else...
} else {
[[NSApp mainWindow] makeKeyAndOrderFront:nil];
}
}
Has anyone ever had experience embedding a field editor (for a NSTextField) inside a scroll view? I'm trying to make the NSTextField scrollable while editing.
Things I've tried:
Dynamically embed it when the custom field editor's -becomeFirstResponder gets called. This semi works; the problem is that when the NSTextField gets resized during editing the custom field editor no longer gets resized with it (and I need this - making an accordion
style application)
Create a "masquerading" field editor out of a NSScrollView, and using NSInvocation forward the methods to the actual surrogate field editor. This is the method I really hope would work; I've implemented all the methods as listed here; but I get an EXC_BAD_ACCESS whenever the field editor is actually loaded (e.g. when I call [customTextField selectText:nil]). I can't seem to pry any information out of the debugger even with Zombies enabled, and looking at the logs of NSObjCMessageLoggingEnabled yields nothing either. It seems like these guys got it working but that was seven years ago.
The last resort would be to drop NSTextFields completely and use NSTextViews (or instead of relying on the field editor mechanism, write one myself), but since I have many rows of data of which only one will be edited at a time, I don't want to instantiate a NSTextView for every single one of them... but then, perhaps it won't be so bad.
I ended up using option 1, and getting it to work without much difficulty. Option 2 was a complete dead end because EXC_BAD_ACCESS popped up everywhere I went.
My custom field editor now keeps a reference to a (custom) scroll view to embed itself in (vvScrollView), and inserts it into the view hierarchy. My code inside my custom field editor (NSTextView) for embedding it inside a scroll view, which is called as soon as the field editor becomes first responder and is automatically inserted into the view hierarchy:
- (void)embedSelfInScrollView {
NSView *realSuperview = [[self superview] superview];
// [self superview] is some kind of private NSClipView class
if ([realSuperview isKindOfClass:[NSTextField class]]) { // the expected behavior: this may change? TODO make less prone to chance
[realSuperview addSubview:[self vvScrollView]]; // insert into view
[[self vvScrollView] setFrameSize:[realSuperview frame].size]; // se the initial size equivalent to control size so it can autoresize the same way
// add the scrollview into the view hierarchy
[[self vvScrollView] setDocumentView:self]; // removes self from previous superview
}
}
The initial problem I had was that I was trying to insert the scrollview into the superview immediately above the field editor's (the private class of NSClipView) which broke almost every automatic sizing option (because I want to be able to resize the NSTextField while editing). Going a step further and bypassing the private class seems to work, but almost seems arbitrary.
So I thought I had covered my bases, but apparently I'm missing a key step or two.
I have an NSPanel that is displayed (makeKeyAndOrderFront:) when an NSStatusItem is pressed. Things work great, but as the NSPanel displays a title bar, the panel is also draggable. (This is undesired.)
The first screenshot shows the panel with "Title Bar" enabled in Interface Builder, in the Appearance category. (Sorry for the blur, things are still under lock and key for now.)
The only change that is made in Interface Builder is unchecking the "Title Bar" checkbox. I then save and re-run, and that's what you see in the second screenshot. While a slight shadow appears, the panel does not.
Things I've tried:
I've subclassed the NSPanel and returned YES for canBecomeKeyWindow and canBecomeMainWindow after a bit of research, but (prior to subclassing) these methods both returned NO regardless of whether I was using a Title Bar or not. So I don't think this is the issue.
I've ensured that the frame for the NSPanel is properly set. It has a good height, and the origin is set properly as well.
Edit: Forgot to Mention:
The application is a menu-bar-only application. In the screenshot below, note that an additional entry was added to Info.plist to enforce this.
I've had problems with this in the past. I was able to resolve it by first "ignoring" other apps, then making it the key window. Give it a shot and see if it works for you.
[NSApp activateIgnoringOtherApps:YES];
[[self window]makeKeyAndOrderFront:self];
Also, try setting the window level to NSPopUpMenuWindowLevel during initialization.
[[self window]setLevel:NSPopUpMenuWindowLevel];
I have also had problems with the way that nib files are loaded on Mac OS X. They're loaded "lazily", which means that they won't be initialized until they're needed. This causes a problem when you're wanting to set specifics on the window, but you can't because awakeFromNib doesn't seem to be called, due to lazy nib loading. To fix this, here's what I've done in the past. In your delegate (or wherever you initialize your window), kick the window into action by accessing the window property on the initialized class:
wc = [[blah alloc]initWithWindowNibName:NSStringFromClass([blah class])];
(void)[wc window]; //just kicks the lazy nib loading into gear
By doing so, you're forcing the nib to initialize. That way, when the user clicks the menubar icon the nib is already initialized, and awakeFromNib has already been called.
While a slight shadow appears, the panel does not.
Are you saying makeKeyAndOrderFront: on this NSPanel object doesn't display it when running your app? I just created a sample project, NSButton triggers the same type of NSPanel to display, and it works fine.. titleBar enabled or not.
http://cl.ly/3d0U3C0P3u2D0m3T1w1N
I was wondering how to remove the proxy icon in the bar of my mac app. I've added an image so you can see what Icon I'm talking about
Thank you in advance!
The icon is included in the titlebar of the application automatically when you've created an NSDocument based application.
You can remove the proxy icon by returning nil from the -[NSWindow representedURL] method. This could be accomplished by using a custom NSWindow subclass with the method overridden; or simply setting the property to nil at the appropriate times.
Be aware, you might loose other functionality you normally get for free by changing this behavior, such as the dirty/clean indicator for the window, or some prompting to save when closing the window.
Alternatively, if you wanted a different image, you could use:
[[NSWindow standardWindowButton:NSWindowDocumentIconButton] setImage:customImage]
Then implement -[id<NSWindowDelegate> window:shouldPopUpDocumentPathMenu:] to return NO to prevent the popup menu from appearing.
If your application isn't actually document based, or the window doesn't represent a document, consider refactoring to present this window a different way, rather than being a document window.
There is some additional information in the Cocoa window documentation.