UIWebView gets cleared after dismissing a fullscreen modal - iphone

I have a UIWebView which loads a html string on viewDidLoad. It detects if the user clicks a link and display a modal view, but when i close the modal view the UIWebView's html has gone! If i use a FormSheet Modal Style the content stays behind, its only fullscreen modals that cause this. Obviously i can just input the html string again on viewWillAppear which fixes it but this causes makes the content flick back on which i don't want. heres my code:
-(void)viewDidLoad {
[self loadArticleText];
...
}
-(void)loadArticleText {
NSString *htmlHead = #"<html><head>...";
NSString *htmlFoot = #"</body></html>";
NSString *htmlContent = [self.articleData valueForKey:#"fulltext"];
NSString *html = [[NSString alloc] initWithFormat:#"%#%#%#", htmlHead, htmlContent, htmlFoot];
[self.articleView loadHTMLString:html baseURL:nil];
[html release];
}
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *URL = [request URL];
ImageViewer *imageView = [[[ImageViewer alloc] initWithNibName:#"ImageViewer" bundle:nil] autorelease];
imageView.imageURL = URL;
[self presentModalViewController:imageView animated:YES];
return NO;
} else {
return YES;
}
}
If i change 'return NO;' to 'return YES;' the webView contents stays, like it should, but obviously it loads the image.
Any help??
Thanks

[self presentModalViewController:ImageView animated:YES];
It looks like you are making a class call rather than an instance call on ImageView.

Related

iOS: Webview causes flicking while navigating to another controller

I use webview in my UIVIewController and load the local HTML file in it using following method.
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:filePath]]];
If I put this method in ViewDidLoad, I can see white flicking while navigating to my controller that doesn't look good.
I tried putting this method in ViewWillAppear like below. I am using webViewLoaded flag to make sure that webview has been loaded then only show the current view else it waits but it is going in infinite loop of waiting!
- (void)viewWillAppear:(BOOL)animated {
webViewLoaded = NO;
webView.scalesPageToFit = allowZoom;
webView.dataDetectorTypes = UIDataDetectorTypeNone;
webView.delegate = self;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:filePath]]];
int count = 0;
while(webViewLoaded == NO)
{
NSLog(#"Waiting...");
[NSThread sleepForTimeInterval:0.1];
if(count++ > 10) break;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)localwebView {
webViewLoaded = YES;
}
I have also tried the same thing in ViewDidLoad but still its going in infinite loop.
Please note that webViewLoaded is "volatile BOOL" but the webview delegate method is not getting called. Not sure what's going on!
Could anyone please help me to fix this. Thanks.
First : You're blocking your main thread and not giving WebView any chance to finish loading. Never block your main thread.
Second : There are two UIWebView delegate methods : webViewDidFinishLoad and webView:didFailLoadWithError: - make sure to listen to both.
If you're trying to wait until WebView completes loading and only show your controller afterwards - use delegation or blocks. Please note that this is not a proper way of doing things - i'm just modifying your example to make it work :
child controller (with WebView) :
-(void)startLoadingWithParent:(id)_parent {
self.parent = _parent;
NSURL * url = [[NSBundle mainBundle] URLForResource:#"resource" withExtension:#"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
[parent showMe:self];
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[parent showError:error];
}
master controller :
-(void)doSomething {
SecondController * ctrl; /// secondController should be created AND has its view loaded at this point
/// ctrl = [SecondController new];
/// ctrl.view;
[ctrl startLoadingWithParent:self];
/// show user that we're doing something - display activity indicator or something
}
-(void)showMe:(UIViewController*)me {
[self.navigationController pushViewControllerAnimated:me];
}
Try using [NSURL fileURLWithPath:filePath]
use Following code for
[self performSelectorInBackground:#selector(webViewLoaded) withObject:nil];
so that it will not affect your UI

How to set scroll position on uiwebview

I want to go to specify line on my uiwebview loaded.
I tried
[webView stringByEvaluatingJavaScriptFromString:#"window.scrollTo(0.0,
100.0)"];
but it's not working. My webview still start with top of the page.
I just wonder its because I load the UIWebview inside UIView.
Check my code below on my UIView:
- (void)loadView {
webview = [[WebViewDetail alloc]initWithFrame:[UIScreen mainScreen].applicationFrame]; //initialize a mainView is a UIWebVIew
webview.managedObjectContext = self.managedObjectContext;
webview.kitab = self.kitab;
webview.currentPasal = self.pasal;
self.title = [NSString stringWithFormat:#"%# %d", self.kitab, webview.currentPasal];
self.view=webview; //make the mainView as the view of this controller
}
and I put the scroll positioning script on my UIWebView:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
int height = [[webView stringByEvaluatingJavaScriptFromString:#"document.body.offsetHeight;"] intValue];
NSString* javascript = [NSString stringWithFormat:#"window.scrollBy(0, %d);", height];
[self stringByEvaluatingJavaScriptFromString:javascript];
}
in this case I want to put my uiwebview go to the bottom of the page when the view is loaded.
But it's totally not working, why?
Am I doing it wrong?
Try
webview.scrollView.contentOffset = CGPointMake(0, 100);
Make sure you set the view controller where you have your web view to be a UIWebViewDelegate, and declare this in the #interface of the header file (.h).
[yourWebView setDelegate:self];
Then, in the webViewDidFinishLoad: method, insert this code:
[yourWebView.scrollView scrollRectToVisible:CGRectMake(0, yourWebView.bounds.size.height + 100, 1, 1) animated:NO];

iPhone Creating a Modal Movie Window

I have created an app that incorporates a table view, detail view, and a web view. I have established a cell in the table view that takes a URL from an RSS feed and will display it in a webview. The URL is an .MP4 file which causes the video to play. The problem I am having is that when the video ends, I cannot go back to the previous screen. The code is below:
DetailViewController.m load webview
if (indexPath.section == SectionHeader && indexPath.row == SectionHeaderEnclosure) {
if (item.enclosures) {
for (NSDictionary *dict in item.enclosures){
NSString *url = [dict objectForKey:#"url"];
NSLog(#" url is : %#",url);
//EXPERIMENTAL
WebViewController *webVC = [[WebViewController alloc] initWithURL:url];
[self presentModalViewController:webVC animated:YES];
}
}
}
WebViewController.m
- (void)loadView
{
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = webView;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:_url]]];
}
//Dismiss modal view
- (IBAction) done:(id)sender {
NSLog(#"done:");
[self dismissModalViewControllerAnimated:YES];
}
I think it would be better to use an MPMoviePlayerViewController. The documentation shows how to set it up with the URL directly using initWithContentURL: and present it modally. You can listen for notifications thet the movie has ended and dismiss it when done. Lots of good stuff in the documentation.

General-Block 56, 1024, 8, 244, 24 Memory Leaks using UIWebView loadRequest

I'm getting memory leaks that i can't figure out through leaks, build/analyze or overall inspection how to repair. I have a very strong notion that it's due to the loadRequest command from my UIWebview loading javascript, but I can't figure out what's wrong.
Here's my setup:
I have a tabbarcontroller that i programatically create with 4 view controllers: a table view, a mapview, another table view and a webview, respectively.
the 1st tableview shows static data.
the mapview shows annotations that when clicked populates a variable of the 4th tab, the webview, and switches to the webview to display a locally stored html/javascript file that is a 3d model
the 2nd tableview is a listing of all the same information each annotation in the mapview represents, just in table form. it has the same functionality in terms of populating the variable, switching and displaying the html/javascript file in the webview
the webview displays the html/javascript file loaded, if not it shows a UIAlertView to select one from the mapview or the list
when i finally get to executing the loadRequest() from the webview, initially everything works fine. however, when i begin to switch between tabs and view different 3d models (i.e. go to the map view click an annotation to show say model x, watch it load in the webview, then switch to the listing table and click a row to show model y (or x too) and watch it load in the webview) i start receiving memory leaks on the ipad, not the simulator. these memory leaks are almost always: General-Block 56, 1024, 8, 244 & 24 and have no responsible frames, libraries or stack traces to follow up with.
in the webview if i comment out the loadrequest line or do a loadrequest with the request object = nil, i have no memory leaks, but when i switch to using a url object that points to the local files (i even tried pointing it to google.com, which has javascript) it erupts in memory leaks.
i've attempted to do each of these:
[self.webView loadRequest:nil];
[self.webView loadHTMLString:#"" baseURL:nil];
[self.webView stopLoading];
in viewWillDisappear of my webViewController in attempt to completely clean out the webview for reuse in the future, but it doesn't seem to be doing much help. i've also attempted doing this prior to doing the loadRequest but i get the same memory leaks.
fyi, i'm running the latest xcode 4.0.2 and the ipad has the latest update, 4.3.2
from a previous post i commented on and haven't heard back from (general-block memory leak) i believe the problem has to do with the fact that webview doesn't know how to fully rid itself of the javascript when i switch views
i did a test with a simple html file with no javascript and the general-block memory leaks are gone. however, i get other cfnetwork / http message memory leaks but that's a different story and not of my concern at the moment.
below is example code of when one of the annotations on the mapView is clicked which triggers the loadModel function in the webViewController:
- (void) mapCallOutPressed: (UIView *) sender {
NSInteger selectedIndex = sender.tag;
MyLocation *selectedObject = [_mapView.annotations objectAtIndex:selectedIndex];
MyModel *model = selectedObject.model;
NSLog(#"Model selected from mapview = %#", model.description);
// Get reference to the webview from the tabBarController (viewController's index=3)
WebViewController *webViewController = [self.tabBarController.viewControllers objectAtIndex:3];
webViewController.model = model;
[webViewController loadModel];
// Switch tabs to the webView
self.tabBarController.selectedIndex = 3;
[self.tabBarController.selectedViewController viewDidAppear:YES];
below is my webViewController.h & .m:
WebViewController.h:
WebViewController : UIViewController <UIWebViewDelegate> {
UIWebView *webView;
NSString *templateRunFilePath;
MyModel *model;
NSString *templateRunTitle;
#property (nonatomic, retain) UIWebView *webView;
#property (assign) MyModel *model;
#property (nonatomic, copy) NSString *templateRunFilePath;
#property (nonatomic, copy) NSString *templateRunTitle;
-(void) loadModel;
WebViewController.m:
- (void) viewDidLoad {
[super viewDidLoad];
NSLog(#"in webview did load");
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.webView.delegate = self;
self.webView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.webView.scalesPageToFit = YES;
[self.view addSubview:self.webView];
}
- (void) viewWillAppear:(BOOL)animated {
if (self.model) {
self.tabBarController.navigationItem.title = [NSString stringWithFormat: #"%# - %#", self.tabBarController.navigationItem.title, self.model.description];
}
else {
UIAlertView *msg = [[UIAlertView alloc] initWithTitle:#"No Model Selected"
message:#"Please select a model from the map or list tab to view."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[msg show];
[msg release];
}
}
- (void) loadModel {
NSString *localURLPath = [NSString stringWithFormat:#"%#/%#/%#", self.templateRunFilePath, self.model.folderName, self.model.modelFileName];
NSURL *url = [NSURL fileURLWithPath:localURLPath];
NSURLRequest *requestObj = [NSURLRequest requestWithURL: url];
[self.webView loadRequest:requestObj];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"WebKitCacheModelPreferenceKey"];
}
-(void)viewWillDisappear:(BOOL)animated {
NSLog(#"webview view will disappear");
[super viewWillDisappear:animated];
//[self.webView loadRequest:nil];
//[self.webView loadHTMLString:#"" baseURL:nil];
self.webView.delegate = nil;
}
- (void)dealloc {
self.webView.delegate = nil;
[self.webView release];
[super dealloc];
}
if you have any advice or corrections, i'd greatly appreciate it. i have < 1 week to figure this out and would highly thank you if you could give me any insight.
thanks!
-Mike
Mike, I am not sure whether you are doing following intentionally or by mistake?
- (void) loadModel {
[self.webView loadHTMLString:#"" baseURL:nil]; // here you are loading... or you have tried with commenting it also?
NSString *localURLPath = [NSString stringWithFormat:#"%#/%#/%#", self.templateRunFilePath, self.model.folderName, self.model.modelFileName];
NSURL *url = [NSURL fileURLWithPath:localURLPath];
NSURLRequest *requestObj = [NSURLRequest requestWithURL: url];
[self.webView loadRequest:requestObj]; // again here you are also loading?
}

Catching modal UIWebView links touches

I have a view controller and I am intercepting the touches on links within the web views it manages.
My main view controller has this method.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
//I can see this request come in upon a touch
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"raw: %#", urlString);
//do some stuff (like figure out what capturedFilename is)
ExplainViewController *explanation = [[ExplainViewController alloc] initWithNibName:#"ExplainViewController" bundle:nil file:capturedFilename];
[self.navigationController presentModalViewController:explanation animated:YES];
}
And this loads a modal view properly.
ExplainViewController has a webView itself. When a user touches a link within ExplainViewConroller I'd like to handle that request too (and present another modal view).
ExplainViewController has this but I get no log activity from either method (the following nor the previous):
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"raw: %#", urlString);
}
I want to know where this link touch request is going and how I can intercept it.
Both mentioned view controllers are using this in their .h
<UIWebViewDelegate>
You mention that both view controllers conform to the UIWebViewDelegate protocol, but is the delegate outlet of the UIWebView in the nib for ExplainViewController.h set to an instance of ExplainViewController. It will not call the method unless the UIWebView delegate property is set.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
BrowserController *browserController = [[BrowserController alloc] initWithUrl:request.URL.absoluteString];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browserController];
[self.navigationController presentModalViewController: navController animated:YES];
[browserController release];
[navController release];
return NO;
}
return YES;
}