UIWebView canGoBack stopped working suddenly when using POST request - iphone

I am loading request like this [resultsWebView loadRequest:searchRequest]; Then I do this
- (void) webViewDidFinishLoad:(UIWebView *)webView {
if ([resultsWebView canGoBack]) {
[goBackButton setEnabled:YES];
}
else {
[goBackButton setEnabled:NO];
}
if ([resultsWebView canGoForward]) {
[goForwardButton setEnabled:YES];
}
else {
[goForwardButton setEnabled:NO];
}
}
canGoBack is always returning NO.
It was working earlier, but it has stopped working suddenly(I have not done any code changes). I don't know how is this possible? Not getting any success to resolve this. There is a question on stackoverflow UIWebView canGoBack and canGoForward always return NO. But it is different as the question author was using loadData and he resolved the problem using loadRequest. But I am already using loadRequest. And again, it was working earlier, but it has stopped working suddenly(I have not done any code changes). Help me.
Cause of issue:
params = [NSString stringWithFormat:#"query=%#", searchTextField.text];
NSMutableURLRequest *searchRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://www.example.com/do/m/]];
[searchRequest setHTTPMethod:#"POST"];
[searchRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
If I use the simple request like below, it works fine.
NSURLRequest *searchRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://www.example.com/do/m/?%#", params]] ];
Thanks

The request may be fail even though you can see the page successfully rendered in the web view, you also need to set those go back/forward logics to – webView:didFailLoadWithError:.

Finally, I found that, if the URL is same in the consecutive POST requests for the loadRequest method then canGoBack does not work. It was working for simple GET requests because URLs were different.
To fix this, I sent the consecutive POST requests with two URLs, which are different from UIWebView perspective but actually same from the server perspective. I am setting the different URLs alternatively for consecutive POST requests, by adding a question-mark(?).
https://www.example.com/do/m/
https://www.example.com/do/m/?
In this way the URLs become different for consecutive POST requests of UIWebView and canGoBack method works.
Still I donot whether it is a bug in UIWebView or we can not use consecutive POST requests with UIWebView to get the canGoBack method works.

Related

Overriding viewDidAppear and have it load specific URL not OK?

I'm reviewing someone else's code and noticed a web form gets refreshed every time you attach an image(click 'add image', find and choose image, return to form, form goes blank). And, it's because the url gets reloaded. In tracking this issue down I noticed that the original dev overrode the viewDidAppear instance method in WebViewController like so:
- (void) viewDidAppear:(BOOL)animated {
NSURL *url = [NSURL URLWithString:self.defaultUrl];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
}
Apple's documentation says
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
I see super isn't called and I think putting in an NSURLRequest is not good practice. I removed the code, added the URL call a button action and all's well so this is mostly a stylistic/academic question.
Do you agree that loadRequest shouldn't be in there? Thanks for your help.
Why shouldnt it be there? loadRequest does its work asynchronously on another thread, so it doesn't block the main thread.
Connects to a given URL by initiating an asynchronous client request.
If it behaves the intended way, is for you to decide.
(Oh and yeah, you should call super in viewDidAppear)

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.

NSURLRequest delegates not getting called on Device Works fine on simulator.

NSURLRequest delegate methods are not getting called when i run the application on the device. It works perfectly on the simulator though. Also its not the case of my view loading before the request is fulfilled because i enable to view to be loaded only once the connection has received the data.
My code requesting url is here. Any help greatly appreciated.
- (void)viewWillAppear:(BOOL)animated
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://-dev01x/content"]; cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
[request setHTTPMethod:#"GET"];
_getData = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"HELLO %#",_getData);
}
Your code as provided here makes no sense:
_getData = [[NSURLConnection alloc] initWithRequest:request delegate:self];
That line returns a pointer to a NSURLConnection object, your variable name is misleading. If you want to block at this point (and does that even work) then it would appear you need to use sendSynchronousRequest at that point.
I do something similar to what you want to do, but in a more traditional way. In viewDidLoad or even in the initWithFrame, I will start up an asynchronous connection, set a flag, and set the view backgroundColor to black or white (I use a spinner too normally). When I get viewWillAppear, if the connection has completed, all is well and I set the various UI elements. If not, then don't do anything, and later, when the connection completes, pull down the spinner and update the UI.
The only way I can think of to block the main thread at the point you are trying to would be to use that synchronous request (which IMHO is a really bad way to deal with this).
The beauty of doing things in the background is that if its taking too long, the user can tap the back button or go somewhere else in the app [in which case you cancel the connection and tear everything down.]
Check url u provide to NSMutableURLRequest when checked in browser gives nothing
NSMutableURLRequest needs valid url

UIWebView Still load the URL even though returning NO

I am handling a UIWebView so that i can control which URLs should be loaded within or not, but some how even though it is retuning the NO , it still load the page. Although documentation clearly says that if you return NO, the UIWebView wont load the page.
When i debug,i can see it is returning NO but still UIWebView does load the URL.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"%#", [[request URL] absoluteString]);
NSString *fullURL = [[request URL] absoluteString];
NSRange range = [fullURL rangeOfString:#"#"];
if (range.length != 0) {
NSLog(#"We need to show the other view");
return NO;
}
return YES;
}
I solved the issue, documenting here so it may help someone else. Actually, the HTML, which we were loading using some javascript which was causing this issue. I found out by just using few plain html and testing with them. Once , we know the HTML is issue, we fixed the html and its working now.
Set a breakpoint or NSLog right before the return YES part. Maybe your method gets called twice for whatever reason, and it returns NO on one, and YES on the other.
First, make sure that you are setting the delegate in viewDidLoad with
webView.delegate = self;
(take care of not setting it 2 times, in a xib file and in viewDidLoad, it has caused me problems before)
Make sure you implement the UIWebViewDelegate in your class, something like this:
#interface RootViewController : UIViewController<UIwebViewDelegate>
Assuming you have taken care of all this and still you face problems. Also since you debugged and are SURE that the delegate method is returning NO. One reason I can think of as to why this is happening is that you are not loading a new page but using something like AJAX.
I tested the following code on 2 kinds of pages:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"THE loadCount is %d", self.loadCount);
if (self.loadCount > 1){
return NO;
}
self.loadCount++;
return YES;
}
Case 1: A webpage where every URL loads a new page. The above code works in this case, and I cannot load any pages after the first load, as required.
Case 2: A webpage in which the first load is a complete new web page. But everything else is loaded with AJAX, in that case, my loadCount does not increase and the pages load fine.
That's all I can think of with the data provided. :)
Same issue here, just to extend the answer above be careful when using rails 4 as backend because turbolinks add javascript to every link and then you can get wrong behavior on your delegate, happened to me returning NO on shouldStartLoadWithRequest and still see the request on my server.

UIWebView and apple rejection

I am doing this in my app :
-
(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.i
NSURL *url = [NSURL URLWithString:#"http://www.mySite.fr"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.myWebView loadRequest:request];
self.myWebView.scalesPageToFit = YES;
}
When i have not the network ( no connexion) nothing is shown ( just a white page witch is the web view).
My question is should i put an alert to the user when there is no network ? how i ca do this ? thanks ? will my app rejected if i don't show an alert to the user ?
Thanks for your answers
While it makes sense to check for reachability, I think you have a better approach using the delegate method webView:didFailLoadWithError: which will tell you if the web view has failed to load your page. In such a case, rather than popping an alert view load some kind of local HTML page indicating that the load has failed if you wish and set a timer to trigger a reload after a while.
As such I don't think Apple will reject you for this unless it is the only thing the App does. But you will have to give a thought on the user experience when the load fails.
I do not think that not checking for a connection will cause your app to be rejected, but you should do it anyway.
Ed Marty has pointed out that my original suggestion of using
- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error
will not work in iOS (thanks!).
This StackOverflow question appears to have a working solution to the problem.