WebView problem - cocoa

My program have two classes, first of them is regular app delegate NSObject. The second one is a NSWindowController subclass with NSWindow and WebView on it, which shows html page from application bundle.
Here is how i call window from AppDelegate:
-(IBAction)showWebViewForm:(id)sender
{
webViewForm = [[WebViewForm alloc] initWithWindowNibName:#"WebViewForm"];
[webViewForm showWindow:self];
}
Here is how i render the webpage in WebViewForm : NSWindowController:
-(void)awakeFromNib{
[NSApp activateIgnoringOtherApps:YES];
[webview setUIDelegate: self];
[webview setResourceLoadDelegate: self];
[webview setPolicyDelegate:self];
[webview setFrameLoadDelegate:self];
[[webview mainFrame] loadRequest:
[NSURLRequest requestWithURL:
[NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"data"]]]];
}
It's work fine, but only for the first time. When i close WebViewForm window and reopen it, webpage is disappearing from WebView. Why is so that, and how to fix it?
UPD Even if embed awakeFromNib code in special new method like -(void)refreshWebview and then call [webViewForm refreshWebview] right after [webViewForm showWindow:self];, still — page loads only for first time, and it's really weird ( Any ideas?

I figure it out by myself. The problem was, that webview closed when it's parent window closed. So, there is special method for case like that:
[webview setShouldCloseWithWindow:NO];

Related

No known class method for selector mainFrame

I'm sure this is a noob question but I've read countless similar problems and not found an explanation specific to this error. I therefore post in the hope of helping future googlers.
I want a clicked button (OSX, Cocoa) to launch a URL in a WebKit WebView. I am using an AppDelegate and the (boilerplate, works-for-everyone-else) code in AppDelegate.m is:
- (IBAction)goClick:(id)sender {
[[WebView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"google.com"]]];
}
The compile-time error is No known class method for selector mainFrame.
I discovered if I create an Outlet in my AppDelegate.h:
#property (nonatomic, retain) IBOutlet WebView *wvOutlet;
it works with:
[[self.wvOutlet mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"google.com"]]];
So it all works with an instance (self.wvOutlet) method but not with the method mainFrame on the class WebView.
Why?
[WebView mainFrame] is attempting to call the class method +mainFrame. No such class method exists.
[self.wvOutlet mainFrame] is calling the instance method -mainFrame. This is correct.
It seems I misspelled webView (an instance) as WebView.
Solution: declare the outlet webView in your AppDelegate.h file:
#property (weak) IBOutlet WebView *webView;
Then you should be able to do:
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"google.com"]]];
Disclaimer: not yet tested!

UIWebview is off loading url

so I have an odd approach for loading bookmarks in a UIWebView in a browser app I am making. For the didSelectRowAtIndexPath in the Bookmarks UITableView, I have this code:
NSUserDefaults *lString = [NSUserDefaults standardUserDefaults];
[lString setValue:[bookmarks objectAtIndex:indexPath.row] forKey:#"loString"];
and then I have a modal for the selected object in the UITableView to another view controller which loads a UIWebView based on this code. So the problem is that the first time I click the table view object, the UIWebview is blank, then the second time it shows the URL that I clicked the first time. PLEASE HELP!
Thanks,
Michael
- (void)viewDidLoad
{
[super viewDidLoad];
NSUserDefaults *lString = [NSUserDefaults standardUserDefaults];
loadString = [lString valueForKey:#"loString"];
NSURL *url = [[NSURL alloc] initWithString:loadString];
NSURLRequest *togo = [[NSURLRequest alloc] initWithURL:url];
[webView loadRequest: togo];
// Do any additional setup after loading the view.
}
The -loadRequest method is asynchronous, meaning that it starts the load in another thread while your main thread's execution continues.
So the first time it's called, it shows a blank screen (because the first request is still running in another thread). The second time, because the first request has now finished, it shows that (while the second request runs in another thread). And so on.
To refresh the screen with the URL contents as soon as they load, you need to implement the -webViewDidFinishLoad method of your UIWebViewDelegate. In that method, you know the URL has finished loading, so if you refresh the web view there it should show the contents.

When a view is dismissed, the presenting view throws EXC_BAD_ACCESS

I'm converting my iPhone app to an iPad version, creating new XIBs for the iPad and rigging them to the existing objective C classes using the ~ipad XIB name.
In the iPhone version, I use the navigation controller to step backwards to the app. This should work just fine in the iPad too, but while the navigation controller does appear, it doesnt respond. In fact its invisible to any interaction, if theres a map behind the navigation controller and you double click back, you just zoom on the map where you clicked.
So I'm including a button in the iPad view which should do the same thing. On press I call a
[[self navigationController] popViewControllerAnimated: YES];
When I call this I get the EXC_BAD_ACCESS. I've gone in to the spooky zombie mode which gives me this
*** -[UIWindowLayer superlayer]: message sent to deallocated instance 0x83bb9f0
Ive determined that 0x83bb9f0 is the presenting layers self.view.layer
I'm using ARC to handle my allocations and deallocs.
THE QUESTION IS: How can I prevent self.view.layer from deallocing? or how can I allocate it again at the proper time so that I dont get this error?
I can provide more code if needed. Thanks so much!!
Edit: Heres where the main page (landing page) is created, and the nav controller
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
landingPage *LandingPage = [[landingPage alloc] initWithNibName:#"landingPage" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:LandingPage];
self.window.rootViewController = self.navigationController;
// [self.navigationController pushViewController:LandingPage animated:YES];
[self.window makeKeyAndVisible];
return YES;
Then here is where the inner view is called:
mapView *MapView = nil;
MapView =[[mapView alloc] initWithNibName:#"mapView" bundle:nil];
[self.navigationController pushViewController:MapView animated:YES];
So I got it!
The XIBs I was creating for the iPad version were windows instead of views. I recreated all of these as views and rigged it up and it worked just fine!

How do you set localstorage so it persist across program runs

I have localstorage for a webview in a program working but it's always wiped out at the beginning of the next program run. I checked the file and it does persist after a program run but at the beginning of the next one, it wipes it out.
Here's my code:
- (void)awakeFromNib {
WebPreferences *prefs = [webView preferences];
[prefs _setLocalStorageDatabasePath:#"~/Library/Application Support/MyApp"];
[prefs setDatabasesEnabled:YES];
[prefs setLocalStorageEnabled:YES];
NSString *resourcesPath = [[NSBundle mainBundle] resourcePath];
NSString *htmlPath = [resourcesPath stringByAppendingString:#"/htdocs/index.html"];
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]];
[window setDelegate:self];
}
Any help would be appreciated! Thanks
look at the doc on WebPreferences, you init it use your webview every time, the WebPreferences is pre WebView, which cause you create a new WebPreferences every time you bring up the application. If you want to keep it persistent, you should init it with initWithIdentifier:"indentifer".
WebPreferences Class Reference
I'm sure you know the risks of using private APIs.
That said, put some breakpoints in there and see at what point the cache is blown away. Try moving the database to a temp location just before that line, then putting it back immediately afterward.

How do you put a normal control into an NSView?

What I'm actually trying to do is put a WebKitView into a ScreenSaver (which inherits NSView). I'm totally new to MacOS X and Cocoa (but I'm very familiar with Objective-C and used some parts of GNUStep). Do I need some laying out? I want to show only one control in the whole NSView.
In your initWithFrame:isPreview: method, create a WebView in the usual way, then, send yourself an addSubview: message, passing the web view:
webView = [[WebView alloc] initWithFrame:frame];
[self addSubview:webView];
If you're wondering what rectangle you should pass as the WebView's frame, read the View Programming Guide. Also, don't forget to release the webView in dealloc (or autorelease it in initWithFrame:isPreview:).
Once you have your web view, you'll need to load a page into it. Set a suitably long animation interval (at least a couple of seconds), and load the page in animateOneFrame:
- (void) animateOneFrame {
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com/"]]];
}
You may also want to handle WebViewProgressFinishedNotification, and put off re-loading the web view until that happens (to compensate for slow or soaked connections). You'll do this with an instance variable, which you set to YES in both initWithFrame:isPreview: and your notification-handler method, and test and set to NO in animateOneFrame:
- (void) animateOneFrame {
if (hasFinished) {
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com/"]]];
hasFinished = NO;
}
}
[aScreenSaverView addSubview:aWebKitView];
But why add a UIWebView into a screen saver view when you can just make the UIWebView take up the full screen on its own? Introducing view hierarchies where they are not needed is not a good idea because it increases the processing needed to display the interface.
You can also not worry too much about your animation interval by calling
[self stopAnimation];
at the end of your animateOneFrame method.

Resources