Why isn't activity indicator working for web view? - objective-c

I am trying to load a web view (called widget) and set an indicator (called indicator) to show that the view is loading (the web page is no larger than www.google.com). The widget loads fine (I haven't included that code) but this snippet, which should send startAnimating to a UIActivityIndicatorView is not working (no animation or even appearance). Everything is connected in storyboard and "not loading" is always logged. This makes me think there is something wrong with my use of UIWebView's loading property.
sleep(2);
[super viewDidLoad];
[indicator setHidesWhenStopped:YES];
if (widget.loading == YES) {
NSLog(#"loading");
[indicator startAnimating];
} else {
NSLog(#"not loading");
[indicator stopAnimating];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
Any thoughts?
Thanks

Try putting your start and stop animating in the delegate methods for the webview:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[indicator stopAnimating];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[indicator startAnimating];
}
Make sure you set the webview's delegate and are conforming to UIWebViewDelegate in your interface.

Related

Generic "help" view which is accessible from all views in uinavigationView

Assuming an application has many views pushed to a uinavigationViewController, each view is different in content.
since the elements in the app are complex, I would like to show a small help view for specific views or elements in a specific view.
Imagine a "?" button that when pressed on will pop a new view in the center of the screen, playing youtube help video, or just a textual HTML loaded from a remote server.
Question: what is the best strategy for doing such a thing?
where should I place this code (App Delegate?)
if so, how would I call it from other views (with URL Parameter)
-(void)showHelpView:(NSString *)theURLString{
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)];
//webView.delegate= self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:theURLString]]];
[window addSubview:webView];
[window makeKeyAndVisible];
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
}
I'd prefer using pseudo-modal views. So that you create view every time, and add it on top of current window. I've used this approach for OAuth 2.0 authorisation popup in my last app.
Basically you create custom UIViewController subclass, provide custom initialisator, such as, for example:
// - (id) initWithURL: (URL*)url {
// ...
// self.url = url;
// ...
// return self;
PseudoModalViewController* pmvc = [[PseudoModalViewController alloc] initWithURL:#"http://www.google.com/"];
After you've created view you add it on top of current window:
UIWindow* window = [[UIApplication sharedApplication] keyWindow];
if(!window)
{
window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
}
[window addSubview:pmvc.view];
In, for example, viewDidLoad you load url obtained in initialisator:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
}
You may even design UI in Interface Builer for that. As a last piece I'd recommend add to include full screen transparent background view to ensure that all views below are disabled.
Oh, almost forgot, you hide that view with just a simple [self.view removeFromSuperview]. Don't forget to provide correct memory management for that view (i.e. release it in time, etc).

UIActivityIndicatorView animation issue

I am using a UIActivityIndicatorView as an IBOutlet. I am trying to control it using [activityView startAnimating] and [activityView stopAnimating].
I have enabled 'Hides when stopped' and 'Animating' behaviors in XIB file.
I want to start animate the spinner for several user actions inside the controller. But after the first [activityView stopAnimating] call it does not response to [activityView startAnimating] call again.
That is mean the spinner is disappeared after the first [activityView stopAnimating] call.
I tried activeView.hidden = NO; before the next [activityView startAnimating] call. But it does not work.
Any idea about this issue?
Edited
After my controller loaded I do follow thing,
do {
[self.activityIndicator startAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[webServiceCallOperation getResults];
[self.activityIndicator stopAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
} while (![webServiceCallOperation isValideResponse] || [webServiceCallOperation isServerError]);
In the same controller I have a IBAction for a button click.
- (IBAction)tappedSearchButton:(id)sender
{
[self.activityIndicator startAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self tappedSearchButtonAction];
[self.activityIndicator stopAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
I noticed that the spinner not begin to animate just after the [self.activityIndicator startAnimating]; call. Using [self tappedSearchButtonAction]; I call to a web service and go to the search results view. The spinner begin to animate just before change the view. That's why I did not see it. But I suppose to animate it before web service call and should animate it while my web service call.
Same behavior of the network activity indicator.
As aadhira suggested check for release and if you are making the calls on the main thread.
[NSObject performSelectorOnMainThread:#selector(SEL) withObject:nil waitUntilDone:YES];
It starts animating because as you say you have enabled Animating behavior in the XIB file. But after you stop it for the first time, it is not animating anymore until you start it again programatically.

Cancel button/touch for UIWebView

I wonderd if there is any way to make the user dismiss the WebView window if he doesn't want it anymore on the screen...?
I looked at this post but i didn't understand it well.
How to cancel a UIWebView?
can anyone give me an example please?
This is the code i have:
CGSize webScreen1;
webScreen1 = [[UIScreen mainScreen] applicationFrame].size;
CGRect webFrame1 = CGRectMake((webScreen1.width/11.0) ,(webScreen1.height/19.0) ,webScreen1.width/1.2,webScreen1.height/1.25);
defaultWebView.frame = webFrame1;
self.defaultWebView = [[UIWebView alloc] initWithFrame:webFrame1];
self.defaultWebView.backgroundColor = [UIColor whiteColor];
self.defaultWebView.scalesPageToFit = YES;
self.defaultWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
defaultWebView.inputView.hidden = YES;
[self.view addSubview: self.defaultWebView];
[self.defaultWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:
[NSString stringWithFormat:(NSString *)#"%#", #"http://www.google.com"]]]];
Thanks!
There is no such thing as cancel a webView, what you need to do is remove the UIWebView from the parent view. If your UIWebView is a subview of self.view then you can provide a button named Close which behaves like this -
- (IBAction)closeWebView:(id)sender
{
[self.webView removeFromSuperView];
self.webView = nil;
return;
}
This should remove the webview from your view.
...way to make the user dismiss the WebView window...
[self.defaultWebView removeFromSuperview];
look I will explain what happenes in the post you attached above and you will understand the technique,
the UIWebview is a component which views an web page, it may be html or other types,
there is one way to hide your webview is to add an action in the html of the webview and ovveride the request in the code of your app,
when you click on link or ahref or any action on UIwebview there is a delegate method which automatically runs before continuing with the request
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
you can add a button or link on the html page and ovveride the request on this method
for example
Thing to click
and in the delegate method
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([[[request URL] absoluteString] isEqualToString:#"http://hideWebView/"]) {
[self.webview setHidden:YES];
return NO;
}
return YES;
}
here you ovveride the request http://hideWebView/ and in the delegate you searched for this request and then hiddes the web view or anything else you want to do

How show activity-indicator when press button for upload next view or webview?

when i click on button which title is click here to enlarge then i want show activity indicator on the first view and remove when load this view.
but i go back then it show activity indicator which is shown in this view.
in first vie .m file i have use this code for action.
-(IBAction)btnSelected:(id)sender{
UIButton *button = (UIButton *)sender;
int whichButton = button.tag;
NSLog(#"Current TAG: %i", whichButton);
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[spinner setCenter:CGPointMake(160,124)];
[self.view addSubview:spinner];
[spinner startAnimating];
if(whichButton==1)
{
[spinner stopAnimating];
first=[[FirstImage alloc]init];
[self.navigationController pushViewController:first animated:YES];
[spinner hidesWhenStopped ];
}}
in above code i have button action in which i call next view. Now i want show/display activity indicator when view upload. In next view i have a image view in which a image i upload i have declare an activity indicator which also not working. How do that?
Toro's suggestion offers a great explanation and solution, but I just wanted to offer up another way of achieving this, as this is how I do it.
As Toro said,
- (void) someFunction
{
[activityIndicator startAnimation];
// do computations ....
[activityIndicator stopAnimation];
}
The above code will not work because you do not give the UI time to update when you include the activityIndicator in your currently running function. So what I and many others do is break it up into a separate thread like so:
- (void) yourMainFunction {
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[NSThread detachNewThreadSelector:#selector(threadStartAnimating) toTarget:self withObject:nil];
//Your computations
[activityIndicator stopAnimating];
}
- (void) threadStartAnimating {
[activityIndicator startAnimating];
}
Good luck!
-Karoly
[self.navigationController pushViewController:first animated:YES];
Generally, when you push a view controller into navigation controller, it will invoke the -(void)viewWillAppear: and -(void)viewDidAppear: methods. You can add activity indicator view inside the viewWillAppear: and call startAnimation of indicator view. You CANNOT invoke startAnimation and stopAnimation at the same time. For example,
- (void)viewWillAppear:(BOOL)animated
{
[aIndicatorView startAnimation];
// do somethings ....
[aIndicatorView stopAnimation];
}
Because the startAnimation and stopAnimation are under the same time, then no animation will show.
But if you invoke startAnimation in -(void)viewWillAppear: and invoke stopAnimation in another message, like followings.
- (void)viewWillAppear:(BOOL)animated
{
[aIndicatorView startAnimation];
// do somethings...
}
- (void)viewDidAppear:(BOOL)animated
{
[aIndicatorView stopAnimation];
}
Because viewWillAppear: and viewDidAppear: are invoked with different event time, the activity indicator view will work well.
Or, you can do something like followings:
- (void)viewWillAppear:(BOOL)animated
{
[aIndicatorView startAnimation];
// Let run loop has chances to animations, others events in run loop queue, and ... etc.
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
// do somethings ....
[aIndicatorView stopAnimation];
}
The above example is a bad example, because it invokes two or more animations in the -runUntilDate:. But it will let the activity indicator view work.
Create a webview. Add a activity indicator to the webview. If you are loading a image via url into the webview then implement the webview delegate methods. Once the url is loaded then stopanimating the activity indicator.
Let me know which step you are not able to implement.

objective-c modalViewController too quick

I am having an issue dismissing a modal view controller on a certain edge case. I display the modal view when I am retrieving a PDF to display in a UIWebView. When the file I am retrieving is very small the modal view will try to dismiss too soon. I present the modal view in the view controller that contains the UIWebView. I dismiss it in the UIWebView's didFinishLoad delegate method.
I am fine with not animating the initial presentation of the modal view... but is that any more safe than what I was doing? does this still have potential to fail, and if so how would you change it? I have been looking through the docs and nothing I have read so far adresses this situation.
//
// This will download the file if not # specific path, otherwise use local file.
// _myFileManager is a helper class and _myFileRecord is the backing data model
//
-(id)initWithNib... fileRecord:(MYFileRecord *)_myFileRecord
{
[_myFileManager cacheFileAsync:_myFileRecord delegate:self];
}
- (void)viewDidLoad
{
// doesn't seem to work, NO for animated does seem to work
[self.navigationController presentModalViewController:_splashController
animated:YES];
_splashController.messageLabel.text = #"Retrieving File...";
}
- (void)recordSaved:(MyFileRecord *)myFileRecord fileName:(NSString *)fileName
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:fileName]];
[_webView loadRequest:request];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
_splashController.messageLabel.text = #"Opening File...";
}
//
// This fails when a small file is already cached to disk and the time
// for the webView to finishLoad is faster than the splashView can present itself
//
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
Try implementing the viewDidAppear in your SplashController, to catch when the view has finished animating, and set a flag. Then you can control if the SplashController's view has finished loading using this flag, and wait for it if it is not finished yet?
E.g.
-(void)viewDidAppear {
if (shouldDismiss) {
[self dismissViewControllerAnimated:YES];
}
readyToDismiss = YES;
}
And in your main VC:
-(void)webViewDidFinishLoading:(UIWebView*)webViewv
{
if (_splashController.readyToDismiss) {
[_splashController dismissViewControllerAnimated:YES];
} else {
_splashController.shouldDismiss = YES; // will dismiss in viewDidAppear
}
}
You can try testing to see if the splashView has finished and use performSelector:afterDelay: to check back later.
My idea is to create a method like this
-(void)dismissWhenReady {
if ( splashView is finished) {
[self.navigationController dismissModalViewControllerAnimated:YES];
} else
[self performSelector:#selector(dismissWhenReady) afterDelay:1.0];
}
}
viewDidLoad fires too early (before it is displayed), you will want to use -(void)viewDidAppear:(BOOL)animated to present your modal view instead along with a flag to know if it is the first load. If it still does not display long enough add a delay for the desired amount of time.