So in my web view controller pertaining to the UIWebViewNavigationTypeLinkClicked part, I have override methods.
Some pointing to urls which fire a download manager, and one part pertaining to a image view controller, in which it loads the image and allows me to save it.
It is held in a navigation controller just as my whole app is.
The first time I tap a image it loads fine, the previous view doesn't open the image as I have called [webView stopLoading]. The second time, maybe third time I tap the same image, the image loads in the same webview BUT also pushes my view controller.
I'm stuck as to why the first/second time i tap the image it's fine, but other times, it does it's own thing.
Below is the relevant code. Any help in solving this would be greatly appreciated.
///////////////
//IMAGE CODE///
///////////////
NSURL *imageURl = [request URL];
NSString *imageFileExtension = [[imageURl absoluteString] pathExtension];
NSLog(#"imageExtension is: %#", imageFileExtension);
NSSet *supportedFileExtensions = [NSSet setWithObjects:#"bmp", #"gif", #"jpg", #"jpeg", #"png", #"psd", #"pspimage", #"tga", #"tif", #"tiff", #"yuv", #"pdf", #"raw", nil];
if ([supportedFileExtensions containsObject:[imageFileExtension lowercaseString]]) {
[webView stopLoading];
//Image manager
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
WebImageViewController *vc = [[WebImageViewController alloc] initWithURL:[request URL]];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
NSLog(#"imageURL");
return NO; ///PART THAT WAS LEFT OUT.
}
Update right above.
Somewhere in updating my app to support iOS 8, I believe I managed to leave out my "return NO;" to each of my if/else statements.
Adding that in stops the webview from loading while passing the image to my custom view controller.
Related
I have a master table and detail view controller. The detail VC shows URLs through a web view.
If using the built in navigation of the master/detail setup, if I go back and then press a different table cell, the detail view will update the web view. This is true whether I use a UIWebView or a WKWebView.
However, within the detail view, without having to go back to the table, I want to give the user the option to view more than one url through the same web view. I am trying to do this in viewwillappear by changing the url for the request. However, the UIWebView (or alternatively WKWebView) continue to show the same url. I can't seem to get rid of the first url.
I've tried all kinds of ways to close or stop the existing web view, clear the cache, delete cookies etc. before reloading the new one but still see the same url. Would appreciate any suggestions. Here is my code and some of the things I've tried that don't work:
-(void) changeURL: (NSNumber*)param {
NSURL *testurl1=[NSURL URLWithString:#"http://www.apple.com"];
NSURL *testurl2 =[NSURL URLWithString:#"http://www.google.com"];
//if param is 1 {
_urlToLoad = testurl1;}
else {
_urlToLoad = testurl2;}
}
Edit: Method below is updateInterface, not viewWillAppear
-(void) updateInterface {
UIWebView *webView;
NSURLRequest *request=[NSURLRequest requestWithURL:_urlToLoad];
webView = nil;//This blocks the web view from loading at all for some reason I can't understand. Setting wkWebView to nil does not block loading.
[webView stopLoading];//no effect
[webView loadRequest:request];
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:request];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
NSString *myDomain = #"www.google.com";
for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
if([[cookie domain] isEqualToString:myDomain]) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
}
//wkwebview version
WKWebView *wkwebView;
WKWebViewConfiguration *wkConfig = [[WKWebViewConfiguration alloc] init];
wkwebView = nil;
wkwebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:wkConfig];
wkwebView.navigationDelegate = self;
[wkwebView loadRequest:request];
[webView addSubview:wkwebView];
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.origin.y = 100.0; // statusbar
webFrame.origin.y -= 100.0; // statusbar 20 px cut from y of frame
webView = [[UIWebView alloc] initWithFrame:webFrame];
}
The UIViewController method "viewWillAppear" has the following signature in Objective-C:
- (void)viewWillAppear:(BOOL)animated
, you implemented it without any arguments.
The result is that, instead of being taken as an override of the original method defined in the superclass UIViewController, it is treated as a brand new, custom method introduced by your subclass; and unless you call it explicitly somewhere, it will never execute.
Source: SDK Reference
I have a screen that shows a web view. However, I allow people to cycle through different web views by updating an object. When I load the first page, the web view loads fine. However, when I try to update the page from the new object in viewwillappear, while other elements such as a title that goes above the webview load fine, the web view does not refresh.
//in viewWillAppear
self.title = self.file.imageDescript;//The title loads fine
NSString *urlBase = #"https://www.~com/images/";
NSString * imagename = self.file.imagename;
NSString *url = [NSString stringWithFormat:#"%#%#",urlBase,imagename];
NSURL *realUrl = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:realUrl];
[webView loadRequest:request];
I have tried various versions of setNeedsDisplay and also applied these to subviews of the web view without success as in this method:
- (void) forceRedrawInWebView:(UIWebView*)webView {
NSArray *views = webView.scrollView.subviews;
for(int i = 0; i<views.count; i++){
UIView *view = views[i];
//if([NSStringFromClass([view class]) isEqualToString:#"UIWebBrowserView"]){
[view setNeedsDisplayInRect:webView.bounds]; // Webkit Repaint, usually fast
[view setNeedsLayout]; // Webkit Relayout (slower than repaint)
// Causes redraw & relayout of *entire* UIWebView, onscreen and off, usually intensive
[view setNeedsDisplay];
[view setNeedsLayout];
// break; // glass in case of if statement (thanks Jake)
//}
}
}
I have read in one SO answer that since IOS8.2, refresh of UIWebView no longer works (as WKWebView) has replaced it. I would switch to WKWebView except that it is not supported in storyboards, apparently, and I have a bunch of stuff going on in the storyboard.
Note: this has nothing to do with refreshing the same web url because content has changed on a server. It has to do with loading an entirely different web url in the UIWebView
Can anyone suggest way to fix this?
I have a ViewController with uiwebvew. This is called to show the webcontents.
My problem is , if the webcontent has links, I want to show that link page in the another instance of same ViewController.
So far I'm unable to do so. I guess I'm missing something here.
Could anyone point my problem here.
Thanks in advance.
-(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
PageDetailsViewController *pdvc = [self.storyboard instantiateViewControllerWithIdentifier:#"PageDetails"];
NSURL *websiteUrl = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:websiteUrl];
[pdvc.webview loadRequest:urlRequest];
[self.navigationController pushViewController:pdvc animated:YES];
return NO;
}
return YES;
When I try to load in same viewcontroller, it's fine it loads. So, my guess is , there may be something wrong with my webview delegate or navigationcontroller.
Any ideas??
pdvc.webview will be nil because its view has not been loaded at the time you're trying to reference it. You should pass the URL to pdvc, and let that controller load its web view in viewDidLoad.
I've a problem with UIDocumentInteractionController. I'm able, through presentOptionsMenuFromBarButtonItem, to display the popover correctly.
When the user touch the barbuttonitem I fire the following method:
- (IBAction)share:(id)sender {
if (docIntController) {
[docIntController dismissMenuAnimated:NO];
docIntController = nil;
}
NSString *fileURL = [(Documents *)(self.detailItem) url];
NSArray *subStrings = [fileURL componentsSeparatedByString:#"/"];
NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:[subStrings lastObject]];
docIntController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
docIntController.delegate = self;
docIntController.UTI = #"com.adobe.pdf";
[docIntController presentOptionsMenuFromBarButtonItem:sender animated:YES];
}
Anyway, when the user touches the print button, and then again the barbutton, the print option menu will not disappear, as you can see in the following image:
Moreover, if the user touches the print option again, the option popover will disappear (but not the old print option) and another print option popover will be created.
Indeed if the user touches outside of the popover to dismiss it, only the first one will be dismissed and the old one is empty as shown below:
I solved this by calling the dismissAnimated method on the UIPrintInteractionController
- (IBAction)share:(id)sender {
[[UIPrintInteractionController sharedPrintController] dismissAnimated:NO];
// remainder of share method code
}
You may want to break the dismissal code (both the UIPrintInteractionController and the DocumentInteractionController) into a separate method and simply call it in the share method. I ran into an issue where the print menu didn't dismiss in portrait mode on the iPad so I added a call to dismiss it in viewWillDisappear.
Well, after reading a bunch of SO posts on this issue, I still can't fix problems with my activity indicator. This indicator is in a view in a tab under the control of its own view controller. It has a view with a UIWebView which loads a local html page just fine. The view is loaded with initWithNibName and then awakeFromNib. Here's the part I think is relevant:
#implementation HelpViewController
#synthesize webView = _webView;
#synthesize back = _back;
#synthesize forward = _forward;
#synthesize aI = _aI;
- (void) viewDidLoad {
_aI = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[_aI stopAnimating];
// Now add the web view
NSString *filePath = [[NSBundle mainBundle]
pathForResource:#"Help"
ofType:#"html"];
[self.view addSubview:_webView];
_webView.delegate = self;
NSURL* fileURL = [NSURL fileURLWithPath:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
[_webView loadRequest:request];
[super viewDidLoad];
}
-(void) webViewDidStartLoad:(UIWebView *)webView {
[_aI startAnimating];
_back.enabled = NO;
_forward.enabled = NO;
}
-(void) webViewDidFinishLoad:(UIWebView *)webView {
[_aI stopAnimating];
if (webView.canGoBack) {
_back.enabled = YES;
_back.highlighted = YES;
}
if (webView.canGoForward) {
_forward.enabled = YES;
_forward.highlighted = YES;
}
}
The navigation buttons work fine. The activity indicator was placed in the nib, but in the main view, not on/over/under the webView. In the attributes, I have Hides When Stopped checked. If I check Animating the indicator is always visible and animated, no matter how I navigate through the UIWebView.. If I uncheck Animating, Hidden is automatically checked for me. In this case, the indicator never shows up. So it's either always on or always off.
I've read quite a bit about cases where you need to have the indicator on a different thread. I'm not sure, but I don't think that applies here (I load a local html page but allow users to navigate off and then back to the local page). But, I seem to have some disconnect; perhaps it is the fact that the indicator is in the main view but the pages are in the webView? Or I'm not calling things in the right methods. Or who knows... Thanks for any help!
You overwrite _aI in your viewDidLoad and never place it in your view hierarchy, so the object you are sending the messages to is never visible and the activity indicator placed in interface build will never change its state, so thats why its either always animating or hidden.