uiwebview youtube starting in landscape thumbnail does resize on rotation - iphone

I have navigation controller with a tableview. When you click on one of the cells it pushes on a view with a uiwebview on it. You are taken to a YouTube page.
When you are on the table view in portrait and click on a cell you see the youtube page in portrait. Changing your orientation the video thumbnail does not refresh. So the thumbnail is smaller. This is fine. I actually prefer it smaller. All the content that would consume 2 lines will then consume 1 line. So in other words everything else adjusts for the new dimensions.
The problem comes in when you start off in landscape. Since the thumbnail doesn't resize on orientation change, changing to portrait mode, the image now goes off the screen, while the rest of the content adjusts correctly.
[webVIew refresh];
does work but it obviously loads the entire page again. So depending on the connection there will be a flicker or possibly the site will go white until its finished loading (on slower connections).
I also tried load the website in an iframe. I asked a similar question yesterday, this was for local pages i was creating. The answer to that question was to put <meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;'> in the head. So I tried that with an iframe going and getting the page. That seemed like a dumb hack to begin with, but i was willing to go there. It wouldn't even load the page at all. I guess because the youtube page i'm loading redirects to yet other page. Upon further research it seemed like there were other issues with the iframe such as scrolling.
So my question is how can i:
A. Get just the thumbnail to resize/reload on orientation change
OR
B. Get the thumbnail to load in the dimensions it would load in portrait mode all the time, even if it was started in landscape.

You should override this method in your UIViewController class and do the resizing there:
(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;

I found the answer, maybe someone could explain it or offer a better solution. There was also an addition bug that I had to work out.
I made sure the uiwebview had the delegate set to files owner.
I changed the parent view when it pushed the view onto the form from:
[self.navigationController pushViewController:controller animated:YES];
to (the important part being the 320, i'm restricting the view to portrait):
[self.navigationController pushViewController:controller animated:YES];
controller.webView.hidden = YES;
controller.webView.frame=CGRectMake(0, 0, 320,367);
3.On the webview i load the url as i always did:
NSURL *url = [NSURL URLWithString:sUrl];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
4.In the webviewdidfinishload i now have:
if (self.interfaceOrientation ==
UIInterfaceOrientationLandscapeLeft ||
self.interfaceOrientation ==
UIInterfaceOrientationLandscapeRight) {
self.webView.frame=CGRectMake(0, 0, 480,227);
}
self.webView.hidden = NO;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
All this would normally have solved my issue, but then i found out that the gdata url i'm getting from youtube service actually gets resolved to a 2nd url. Then i guess youtube changed their url format so it is forwarded to a 3rd url. This means that my didfinishload code was being called before the final url had loaded. To solve this i added:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([[[NSString stringWithFormat:#"%#",request.URL] substringWithRange:NSMakeRange(0, 26)] isEqualToString:#"http://m.youtube.com/watch"]) {
NSString *sUrl=[NSString stringWithFormat:#"%#",request.URL];
sUrl = [sUrl stringByReplacingOccurrencesOfString:#"http://m.youtube.com/watch?" withString:#"http://m.youtube.com/#/watch?"];
NSURL *url = [NSURL URLWithString:sUrl];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
return NO;
}
//NSLog(#"request:%#",request.URL);
return YES;
}
Which im sure could be better but basically i tell it to ignore the 2nd url, and make my own change to go to the 3rd url.

Related

iPad: Cannot load facebook page wall in UIWebview

Its already too long i am struggling with this issue. After searching a lot I decided to post a question here.
What my app does
Captures photo
Uploads the photo on the wall of the page
Displays the facebook page wall in a UIWebview after upload is complete
Everything was working as expected 4 days back :) Suddenly something went wrong :(
Code
NSString *facebookPageURL =#"https://m.facebook.com/pages/<myPageName>/<myPageID>?v=wall"
UIWebView *webView = [[UIWebView alloc] initWithFrame:kAppFrame];
[webView setUserInteractionEnabled:NO];
[webView setBackgroundColor:[UIColor clearColor]];
webView.delegate = self;
[webView setHidden: YES];
NSURL *url = [NSURL URLWithString:[facebookPageURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] relativeToURL:[NSURL URLWithString:#"http://login.facebook.com"]];
NSMutableURLRequest *request = nil;
if(url)
request = [NSMutableURLRequest requestWithURL:url];
[webView loadRequest:request];
[self.view addSubview:webView];
[webView reload];
[self.view bringSubviewToFront:webView];
webView = nil;
Scenario
If I open the url facebookPageURL in Safari in iOS Simulator it works well
If I open the url in any browser on Mac it works well
In webView I see a white screen
If I change the facebookPageURL to remove ?v=wall to ?v=info I am stil able to see the page.(not blank screen atleast).
Note
1. My facebook Page is NOT unpublished and is visible.
2. I have cross checked the facebook page permissions.
I suspect there is something changed on facebook side overnight.
Please guide.
It seems the ever capricious Facebookhas removed the permission to view the wall. I came to this conclusion as when I tried the same thing in separate project I was getting both info and photos but for wall it turned grey
So Here the solution for al those suffering or might suffer form this issue.
I am getting a dictionary in response to the post
{"id":"<imge_id>","post_id":"<post_id>"}
http://www.facebook.com/photo.php?fbid=<imge_id>
and it works like a charm.
Edit:1
Just now I figured out an issue
For the pages with an age restriction, we need to authenticate which SSO doesn't supports for UIWebView inside my app.
I had to downgrade to NOT using SSO anymore. And now it works no matter what.
Just to add here you can find how to neatly downgrading to non-sso mechanism.
I think it's will help you
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([(NSMutableURLRequest *)request respondsToSelector:#selector(setValue:forHTTPHeaderField:)]) {
[(NSMutableURLRequest *)request setValue:#" Safari/537.1" forHTTPHeaderField:#"User_Agent"];
}
}
I hit my head against the wall on this one for a while. The same request and webview on an iPhone will pull up a facebook page, but results in a blank white page on an iPad. Changing user agent doesn't solve the problem.
I was able to hack around it by pulling down the HTML for the page I was looking for using stringWithContentsOfURL and then loading the HTML manually into the webview
You don't want to call [NSString stringWithContentsofURL from your main thread if you can help it, since it will hold up your thread until the results come back. Here is my solution for running it in the background and updating a UIWebView that I had already created and added to my subview called "facebookWebView":
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *rawHTML = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://www.facebook.com/link.to.your.page.on.facebook"] encoding:NSASCIIStringEncoding error:nil];
dispatch_async(dispatch_get_main_queue(), ^(void) {
[facebookWebView loadHTMLString:rawHTML baseURL:[NSURL URLWithString:#"http://www.facebook.com"]];
});
});
Hope this helps some people.

Webview content not resizing

I have a webview.. with the following attributes:
1.scalesPageToFit
2.Autoresizing masks
3.contentmode = aspectFit
After loading it fits to the page as obvious. But as soon as i zoom in and then zoom out to normal; rotating the device doesn't fit completely.
As a tweak, i have checked if the orientation mode is landscape reload the web page. I read various posts in this regard, but couldn't find any solution.
You have 2 folowing options:
Add this into head section of your html file:
<meta name="viewport" content="width=device-width" />
Or call [myWebView reload] when orientation changes
You can use this Code
NSString *website =#"http://www.google.com";
NSURL *url = [NSURL URLWithString:website];
NSURLRequest *requestURL =[NSURLRequest requestWithURL:url];
mywebview.scalesPageToFit = YES;
mywebview.autoresizesSubviews = YES;
[mywebview loadRequest:requestURL];
It took more than 2 days to find out the reason causing this issue. Actually webview was working correctly except the fact that if you try to use PinchGesture to zoom out further.. webview will baheve in the same way.
To overcome this issue, we need to set the zoom scale of scroll view in Webview under willRotate method. However, it's animating weirdly but one can make a guess where the issue lies.

UIWebView content doesn't load until after view is shown

I have a UIView which, on viewDidLoad creates and shows a UIWebView. The web view doesn't actually show its contents until the view has actually appeared though. The navigation bar appears with the view during its animation process but the web view is populated a second after the animation has finished. How can I make the web view load the contents BEFORE animation begins. Here is my code, thanks:
-(void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Help";
NSString *html = #"my html contents goes here, all local and all within a string - does contain one BG image though";
UIWebView *webView = [[UIWebView alloc] initWithFrame:_webFrame];
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithpath:path];
[webView loadHTMLString:html baseURL:baseURL];
[self.view addSubView:webView];
[webView release];
}
I think a UIWebView needs some time to initialize, since it uses the WebKit engine.
You could try adding a simple timeout before actually pushing the new viewcontroller or show a placeholder during the 'push' animation.
As far as I know, a UIWebView has to be on screen in order to load and render.
i'd try the following:
create and add web view on the calling view controller.
set frame of the web view in a way only one pixel is shown on screen.
load html content.
push to new ViewController, remove Web View from old parent and add to new one.
might work, but it's really not worth the hassle, why not try to "solve" the issue by adding a load indicator or a placeholder text?

Preloading a UIWebView, avoiding white screen flash

I'm working on an app that has table navigation to eventually drill down to UIWebView that displays various information. However, the transition from the slickness of UITableView to the slow wonkiness of UIWebView is jarring for the user so I want to improve that experience however I can.
Specifically, the background of both the tableViews and UIWebView pages have black backgrounds, but when I open the UIWebView it flashes empty white for about a second (this is the case for both local and remote HTML files.) How can I (ideally) preload this process, or (at least) make the "flash" be all black rather than all white? I tried making the view / webView's background black but that didn't seem to help.
In my app right now, when a user selects a cell, the app just loads up the UIWebView subclass and pushes it on the navigation stack. The UIWebView subclass has an activity indicator that starts & stops animating on WebViewDidStartLoad and WebViewDidFinishLoad, which works fine, but it doesn't do anything to help the "white flash."
I have tested it... I'm sending the two method that I have used...
- (void)viewDidLoad {
[super viewDidLoad]; //objWebView is the outlet of UIWebView
[objWebView loadHTMLString:#"<html><body style=\"background-color:black;\"></body></html>" baseURL:nil];
//the more the delay the errors will be less so within 0.1-0.3 would be fine
[self performSelector:#selector(loadURL:) withObject:nil afterDelay:0.1];
}
-(void)loadURL:(id)sender{
[objWebView stopLoading]; //added this line to stop the previous request
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[objWebView loadRequest:req];
}
here I'm performing the request after 0.1 sec, other wise it will look white as in your case. Or you can give your delay time depending upon the time.. Cheers :)
Try in your
-(void)viewDidLoad{
myWebView.hidden = YES;
Then in
-(void)loadURL:(id)sender{
myWebView.hidden = NO;
I used:
[webView setHidden:YES];
[webView setDelegate:self];
when creating my webView and making the request and then added this delegate method to handle completed requests:
- (void) webViewDidFinishLoad:(UIWebView*)webView{
[webView setHidden:NO];
}
Successfully done it.
You have to create a view in Interface Builder first.
Then load the html to the webview using a initWithFrame in the init of your ViewController that contains the webview(this is where the magic happens):
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webView = [[UIWebView alloc] initWithFrame:webFrame];
Then simply load the webView into the view in viewWillAppear:
[viewWeb addSubview:webView];
This is really a question of interface designing, which is faster paint directly on the view or paint in a subview and then paint that subview in the view?
I had solved this problem years ago, using the common method of hiding the UIWebView behind a UIImageView, then removing the UIImageView after a delay.
But it suddenly came back, I think on iOS 7.0.4. It was occurring on a brand new iPad Air, as well as an older iPad mini non-retina. After two days of hair-pulling, I finally found a work-around.
Let's say you have webview which is restricted to landscape orientation, initialized like this:
WebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024.0f, 768.0f)];
And then you make it visible after pre-loading, with eg bringSubviewToFront or setHidden:NO on the webview (or alternatively with setHidden:YES or removeFromSuperview on the UIImageView). But instead of seamlessly switching the views, there's a flash and the background color blinks for about half a second.
The fix is to change the size of your webview, ever so slightly:
WebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024.01f, 768.0f)];
The problem and fix is highly reproducible. It works with a change as slight as the fourth decimal place (1024.0001f). At the fifth decimal place (1024.00001f), the flash returns. The value of the height (768.0f) didn't seem to matter.
Or, instead of working around the problem, you could just set the background color of your webview to whatever background color you're using. Unless you're using an image of course.

UIWebView delay in loading local content

I'm displayed a small amount of local content in a UIWebView, roughly 3 paragraphs of text and one 100x100px image. When the UIWebView is pushed onto to the nav controller, it takes about half a second before the content is displayed. This occurs on the device, not in the simulator. Obviously the UIWebView needs to do some work before displaying the content, but is there some way I can do this before the pushed view appears? I have not had any luck doing this myself.
Here is where I'm creating and pushing the view controller which contains the UIWebView:
ArticleViewController* viewController = [[ArticleViewController alloc] init];
viewController.article = article;
[viewController view]; //touch the view so it gets loaded
[viewController loadWebView]; //load the web view content
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
And here is the loadWebView method:
-(void)loadWebView {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSString* content = article.content;
NSString *html = [NSString stringWithFormat:#"\
<html><body style='background-color: transparent'><style type=""text/css"">body {font-family: helvetica; color: black; font-size: 10pt; margin: 10px 10px 10px 10px}</style>\
%#<div style='text-align:center'><a href='13443574_9709e4cf37.jpg?photographer=test' style='-webkit-tap-highlight-color:rgba(0,0,0,0);'><img src='13443574_9709e4cf37.jpg' height='160' width='230'></a></div></body></html>", content];
[self.webView loadHTMLString:html baseURL:baseURL];
}
Previously I had [viewController loadWebView] in the viewDidLoad method, but the result seems to be the same. A blank screen when the viewController is pushed, followed by the content loading half a second later.
Any ideas?
Problem Confirmed
I too see a half-second or more delay with a white screen before my UIWebView content appears. This happens only on the first use of a UIWebView during that run of the app. Successive appearances of UIWebView are nearly instantaneous. So it seems to me and other folk that the delay must be due to WebKit libraries needing to load and initialize.
Warm-up WebKit
You cannot eliminate the delay. But you can move that delay to the start of your app, to lessen the annoying effect of "blank screen" to your users. The trick is to load UIWebView with a bogus page off-screen, during your app's launch. Build a minimal HTML5 web page in a hard-coded string. I use a correct and valid HTML5 content to minimize the time taken by UIWebView/WebKit to analyze.
This technique works noticeably well on real hardware (iPhone 3GS), not just the iOS Simulator.
In my app delegates didFinishLaunchingWithOptions method, the bottom of the ARC-compliant code looks like this:
…
[self.window makeKeyAndVisible];
// Performance optimization: Warm up the UIWebView widget and its related WebKit libraries.
// We are choosing the trade-off between (A) a slight delay here during app launch to create and abandon a bogus UIWebView instance, and
// (B) a flash of white and noticeable delay as the UINavigationController slides in from the right the first UIWebView we display during the app run.
UIWebView* bogusWebView = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
NSString* html = #"<!doctype html><html lang=en><head><meta charset=utf-8><title>blah</title></head><body><p>bogus content</p></body></html>";
[bogusWebView loadHTMLString:html baseURL:nil]; // Load the page.
bogusWebView = nil; // Not really needed, but self-documents that we intend to discard this object.
return YES;
This technique seems to reduce most but not quite all of the approximate half-second delay during the user's first appearance of UIWebView on screen. I conclude that most of the delay is due to WebKit warming up, but there must be some overhead related to graphically presenting a UIWebView on-screen. If so, we cannot eliminate that remaining overhead with off-screen work. But nevertheless, this technique eliminates most of the initial delay. So the user's first impression of my app won't be "slow".
You're going to make the user wait, the only question is: is it before or after the webview appears? If you're set on "before", then you should create the controller, load the web view, but wait to push it until the -webViewDidFinishLoad: delegate method fires. Once you receive that, you can push the view.