WebView Activity Indicator won't stop spinning - iPhone Objective-C - iphone

I would like it to stop spinning once the website finishes loading...
The code I have it:
in my .h
IBOutlet UIActivityIndicatorView *activityIndicator;
in my .m
- (void)webViewDidStartLoad:(UIWebView *)webView {
[activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[activityIndicator stopAnimating];
self.view = webView;
}
I then hooked it up to files owner in the nib. It spins, but doesn't stop! Any suggestions? Thanks!

Does the web view ever actually finish loading? Set a breakpoint and see if you ever even hit that method.
And, for completeness...you do have the delegate of the webview set to your view controller, correct (I assume you do, as it starts animating, but you never know)?
There are two ways you can set the delegate of the webview. If you have it in your nib, control click on the webview and drag from the delegate property to File's Owner. Or, in viewDidLoad, just say _webView.delegate = self;
UPDATE: After our conversation, and in regards to the comments below, I just want to add this for completeness, and for anyone else who sees this in the future with the same issue. The reason your webView was getting huge after it finished loading was because you were assigning it to the view property of your view controller when you said self.view = webview. No need for that. Take that out, and you'll be fine.

Make sure you have the correct toggle settings on the actual UIActivityIndicatorView object in Interface Builder and make sure it's linked correctly. I believe you want "hides when stopped".
Also make sure you have the WebView Delegate implemented.

should work the way you implemented it.
Add following code
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[loadIndicator stopAnimating];
}
Maybe your UIWebView doesn't finish loading properly.

Related

How to add Pop up Button in UIWebView

The deafult pop up is get opened when I long press the music play option in any url from UIWebView.
I Want to add one more button in the pop up..Is it possible to do it..
Like I want to add FETCH button.
And Can I make changes in the default pop up functioning which is OPEN and COPY. shown below
I come to know that by google -
First of all, you really can’t add additional menu items to the default ones of the standard contextual menu. But you can switch off the contextual menu using a certain CSS property. So the solution would be to switch off the default menu and implement your own from scratch. And to implement your own contextual menu, you have to first catch the tab-and-hold gesture, get the coordinates of the finger on the screen, translate these coordinates into the coordinate system of the web page and finally look for the HTML elements at this location.
NEW ANSWER:
Looks like this is what we want, here:
https://stackoverflow.com/a/3198220/700471
OLD ANSWER:
Okay, after some research, here's the deal:
What you describe in your question seems accurate:
First of all, you really can’t add additional menu items to the
default ones of the standard contextual menu. But you can switch off
the contextual menu using a certain CSS property. So the solution
would be to switch off the default menu and implement your own from
scratch. And to implement your own contextual menu, you have to first
catch the tab-and-hold gesture, get the coordinates of the finger on
the screen, translate these coordinates into the coordinate system of
the web page and finally look for the HTML elements at this location.
So you are planning on implementing your own popover controller with contextual menu--fine, I won't get into that at all, I will assume you know how to do that.
What your question seems to be is, how do you take a long-tap gesture in the UIWebView and transform it into the coordinates of the webpage to find the DOM element that was selected, and use that as a context from which to generate your popover menu.
What I found was this, specifically this with this line of code:
NSString *js = [NSString stringWithFormat:#"document.elementFromPoint(%f, %f).innerHTML", touchPoint.x, touchPoint.y];
That looks like the JS you would need to figure out what element had just been long-pressed, and of course you would need to do some figure-figure to see if it was a link and execute your context menu from there, but that's not something I've looked into.
Some further thoughts:
Probably the easiest course would be to attach a UILongPressGestureRecognizer to your UIWebView (this can be done easily in a nib) and make sure that the "Sent Action" points to an appropriate IBAction on your ViewController. (I suppose you could use the delegate outlet as well, but I have never needed to do that.)
In any case, you can use the locationOfTouch:inView: method of your gesture recognizer, and the view you will probably want to use will be the UIWebView's content view, which I believe you can get with something like myWebView.scrollView.subviews[0] (or the objectAtIndex: variation if you are not using the new array index subscripts).
Anyway, I think I have provided enough to answer your question.
EDIT:
Okay, so you are still having trouble with this, so I went and made a test project and got it to work. One thing that is slightly annoying about this is that WebKit somehow adds a "buffer" area around objects in the DOM, meaning that if you touch slightly next to a link it will still highlight, but when you use the JS command elementFromPoint it doesn't do that, so you kinda have to touch more carefully to trigger the popup using this method. But, it works.
I made a blank project with the "single view" template, and threw a UIWebView into the xib, pointed its delegate outlet to File's Owner. Then I put a UILongPressGestureRecognizer into the xib, attached to the UIWebView. I set its delegate as File's Owner, and set its selector outlet to the longPressDetected IBAction in File's Owner. I also unchecked "Canceled in View" in the recognizer's properties in Interface Builder.
Here is the code for the view controller.
Interface:
//
// WVTViewController.h
// WebViewTest
//
#import <UIKit/UIKit.h>
#interface WVTViewController : UIViewController <UIWebViewDelegate, UIGestureRecognizerDelegate>
#property (nonatomic, weak) IBOutlet UIWebView *myWebView;
#property (nonatomic) BOOL didFirstLoad;
- (IBAction)longPressDetected:(id)sender;
#end
Implementation:
//
// WVTViewController.m
// WebViewTest
//
#import "WVTViewController.h"
#interface WVTViewController ()
#end
#implementation WVTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Just load google.
NSURL *theURL = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
[self.myWebView loadRequest:request];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if (!self.didFirstLoad) {
// Disable the default contextual menu.
[webView stringByEvaluatingJavaScriptFromString:#"document.body.style.webkitTouchCallout='none';"];
}
}
// Called by the gesture recognizer.
- (IBAction)longPressDetected:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan) {
NSLog(#"Long press detected.");
CGPoint webViewCoordinates = [sender locationInView:self.myWebView];
NSLog(#"WebView coordinates are: %#", NSStringFromCGPoint(webViewCoordinates));
// Find the DOM element
NSString *locatorString = [NSString stringWithFormat:#"document.elementFromPoint(%f, %f).innerHTML", webViewCoordinates.x, webViewCoordinates.y];
NSString *result = [self.myWebView stringByEvaluatingJavaScriptFromString: locatorString];
NSLog(#"Element Found: %#", result);
}
}
// Necessary or the gesture recognizer won't call the IBAction.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
#end
As I said, I tested the above code and it works fine. You can of course change up your JS and use something other than innerHTML, such as tagName or href or whatever you like. Multiple checks may be necessary for what you're trying to do, possibly with queued JS commands (which would be lame), unless you could JSON-stringify the DOM object, pass it back to the Objective-C, convert to native objects and perform your checks in that environment--but, I'm no JS pro and I'm not going to investigate that.
As a note, I was a bit surprised that the coordinates that worked for elementFromPoint were the touch coordinates within the UIWebView itself. I had rigged up a whole block of code that iterated through myWebView.scrollView.subviews and found the content view, then called locationOfTouch:inView: on that view. But I was getting funky behavior, so on a hunch I used the webview coordinates and it worked fine, even on a big webpage when I was scrolled off to the side and down. I suspect that some kind of Apple-programmed behavior inside the webview may translate those coordinates. Possibly the JS's coordinate system is altered based on the way the content view is moved around inside the scrollview--that makes the most sense to me.
The proper and accurate way to answer this question is below link
http://www.icab.de/blog/2010/07/11/customize-the-contextual-menu-of-uiwebview/
you can fire the event with something like this:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if( navigationType == UIWebViewNavigationTypeLinkClicked )
{
// Handle your URL click here (open the popup menu)
// ...
return NO;
}
return YES;
}
don't forget to delegate the UIWebView

UIAlertView Dynamically in iPhone App

I want to display dynamic UIAlertView and Indicator within it when data is loading from web-service.
Also I don't want any button on UIAlertView. And it will be stopped automatically when data will be loaded successfully.
How can I implement it.?
Just declar UIAlertView and then your activity indicator, make indicator a sub view to alert view and then when your data has been loaded from web service dismiss with this instance method
– dismissWithClickedButtonIndex:animated:
If you are using WebView then write startAnimating ActivityIndicator in ViewDidLoad and this delegate method will call by itself when your data will be loaded
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[ActivityIndicator stopAnimating];
}
Hope it helps.Thanks :)
Then use MBProgress HUD or SVprogress HUD
https://github.com/jdg/MBProgressHUD

iOs show checkmark when finished loading

I have an implanted Facebook in my app. When it is posting something on Facebook it is displaying a Activity Indicator wich works as it should but I want to show a checkmark when it is finished with posting. I am not sure how to do this. This is the code when it is finished with loading
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
//Stop the spinner
[ActivityView removeView];
}
Look at - https://github.com/jdg/MBProgressHUD
It is very easy to use and has many examples.
If you're using a XIB, place the checkmark in an imageView and then position it where you want in your view. Wire it to an IBOutlet so you can access it from your view controller. Set the imageView's property to be hidden initially.
In your didReceiveResponseMethod, update the imageView's property to:
imageView.hidden = NO;

UIWebView loading but not displaying website (XCode 4, iOS SDK 4.3)

i'm going to write an app including an UIWebView. So first I wanted to try it out by just simply loading an URL.
Created the UIWebView in Interface Builder
Hooked up to the code
#property(nonatomic,retain) IBOutlet UIWebView *webView;
viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
if(!webView)
{
webView = [[UIWebView alloc]init];
}
webView.delegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]]]; }
also I implemented the didFailLoadWithError and webViewDidFinishLoad delegate methods.
webViewDidFinishLoad is called and indicating that HTML has been loaded.
Problem is: Even though webViewDidFinishLoad is called, the UIWebView doesn't display the website. It's only showing white color. The scroll bars right and at the bottom are shown when the UIWebView is touched and dragged but not content is visible. Nowhere found anything. Seems quite strange..
EDIT
This screenshot shows the connections of the xib:
Connections
If you hooked everything up in Interface Builder correctly, the following lines should not be needed:
if(!webView)
{
webView = [[UIWebView alloc]init];
}
webView.delegate = self;
Try removing them and see what happens. Also, put an NSLog(...) in the webView:didFailLoadWithError: callback and see if it is output.
I got it.. I used synthesize in the following way:
#synthesize webView = _webView;
So it was necessary to call the UIWebView in the following way:
[self.webView loadRequest:...];
New to this naming convention which is why i'm not used to necessity of self
Have you checked the File's Owner connect to the webView you declared?
Besides, webViewDidFinishLoad does not mean the HTML was loaded!
Whatever the content is loaded successful, this method will be called.

webViewDidFinishLoad: Firing too soon?

I'm trying to transition between loading of different web pages by hiding the webView while it is loading a page. However, I'm seeing that some image intensive websites are causing webViewDidFinishLoading to fire too soon and when I show the webView at that point then for a split second you get a view of the previous page. Any ideas on how to resolve this?
If there's Javascript on the page, you may need to wait for it to finish. The easiest way seems to be to send some javascript to the page to be executed:
-(void) webViewDidFinishLoad:(UIWebView *)webView
{
NSString *javaScript = #"<script type=\"text/javascript\">function myFunction(){return 1+1;}</script>";
[webView stringByEvaluatingJavaScriptFromString:javaScript];
// done here
}
Having said that, I seem to still see cases where the webview isn't quite updated within webViewDidFinishLoad.
I've encountered this problem as well. Although I haven't found a solution, I've worked around the problem by introducing a 0.5 second delay before showing the UIWebView once the webViewDidFinishLoading delegate method is called.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self performSelector:#selector(displayWebView) withObject:nil afterDelay:0.5];
}