Problem with MBProgressHUD while loading images from server - iphone

I have a server that provides a JSON with certain parameters and the name of an image. Then I get the image with the name provided. All this is done in one function called loadingOfImageAndInformation. I use the MBProgressHUD as follows:
[HUD showWhileExecuting:#selector(loadingOfImageAndInformation)
onTarget:self withObject:nil animated:YES];
Which should show the progress thingy when this method is currently running. Now, inside the method I use a ASIHTTPRequest to retrieve all the data I need. Which means that sometime it will jump from that method to the request methods (to retrieve the image and assign it to the UIImageView on the requestLoadDone).
Now, the problem is that the MBProgressHUD thingy only shows until the parameters are shown (the image description I put on a label, the description I got from JSON) and not until the parameters AND image are shown. So basically the loader disappears BEFORE the image is on the imageView.
This is the code in question:
- (void) loadingHudAlert {
NSString *loadingMessage = NSLocalizedString(#"Please Wait",
#"Message displayed when the loading spinner is on");
HUD = [[MBProgressHUD alloc] initWithView:self.view];
HUD.minShowTime = 1.0;
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = loadingMessage;
[HUD showWhileExecuting:#selector(loadingOfImageAndInformation)
onTarget:self withObject:nil animated:YES];
}
The ASIHTTPRequest does all request on an asynchronous mode. Without a queue.
Thank you for your feedback!!!!

I solved it using a boolean, if the method requestLoadDone is finished the bool turns to be NO and while the boolean is YES the loadingOfImageAndInformation will run (which means will run until the image is correctly retrieved.) I haven't posted this as an answer since maybe someone has a better solution.

So you're saying that the HUD disappears before the image is shown at your imageview, don't you? Maybe this is more due to how cocoa processes this stuff than MBProgressHUD problem.
How are you assigning the image? Have you tried?
[yourimageview setNeedsDisplay];
What I'm trying to say is that, if this is how cocoa manages the imageviews showing stuff, maybe you can try to "force" the reload or displaying to be done before.

Related

Image Loading in Thread Makes Navigation Transition Choppy

I have an app where a user clicks a photo thumbnail which triggers the next viewcontroller to be pushed on the navigation stack which is responsible for displaying a larger version of the picture. When the photo thumbnail button is pushed, I send the photos alasset reference to the next viewcontroller which loads it in its viewDidLoad method as follows:
dispatch_async(dispatch_get_main_queue(),
^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImageView *tempMyImageView = [[UIImageView alloc] initWithImage: [UIImage imageWithCGImage:[[[self myAsset] defaultRepresentation] fullScreenImage]]];
[self setMyImageView: tempMyImageView];
[myViewContainer addSubview: [self myImageView]];
[tempMyImageView release];
[pool drain];
});
Everything seems to work OK, except for when I send a large image (like one I took from my camera), the navigation transition is choppy. Does anyone know how to fix this?
You might try just loading the image after the transition is done.
Also of note is that you're not actually doing that in a new thread, as you specified the main queue. Not that that would be a good idea here, as you don't want to execute UI code on another thread.

Trouble with Displaying an Activity Indicator while Data Loads

I feel as though there is a really simple solution to my problem, but thus far I have had little success... I want to load my initial .xib file (exiting the default.png splash screen early), so that I may display an activity indicator while loading my html data and setting the text label fields created by my xib file.
Unfortunately, when I execute the following code below, I display my default.png image until all of the data is loaded from each website... What may I change in order to first display my mainView, then start the activity indicator, load my html data, and set the text labels in my mainView?
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[activityIndicator startAnimating];
[self runTimer];
}
- (void)viewDidAppearBOOL)animated {
[super viewDidAppear:animated];
[self loadHTMLData1];
[self loadHTMLData2];
[self loadHTMLData3];
[self loadHTMLData4];
[activityIndicator stopAnimating];
}
...
It's all to do with how iOS updates the ui. When you call
[activityIndicator startAnimating];
it doesn't mean start animating immediately, it means you're telling the ui the next time you are updating the display, start animating.
All of this updating happens on the main thread (if you haven't made a thread, you're already on the main thread) so if you do something else that takes a long time, it will do this before updating the display.
There are a few ways to fix this and they all involve making another thread that runs in the background.
Take a look at NSOperation (and NSOperationQueue) - this will let you queue up individual tasks that iOS will run in the background for you. then when they are complete you can update your display again and turn off your activity indicator.
There's NSOperationQueue tutorials all over google :)
Hope that helps.

iPhone UILabel not updating

I know there are lots of similar questions floating around, but none of the answers seem to fix my problem. I have an app that uses an NSURLConnection to download a file, and then does some calculations on the downloaded file. I set up a UILabel to display the current loading status (eg: "Loading file", "Parsing file"). I update the UILabel in the didReceiveResponse and connectionDidFinishLoading function of the NSURLConnection delegate, as well as some other places in my code. I update it by calling the following function:
[self performSelectorOnMainThread:#selector(updateProgress) withObject:nil waitUntilDone:NO]
where -(void)updateProgress is a function I defined to call [theLabel setNeedsDisplay]. I NSLog'd it, like
NSLog(#"theLabel: %#\n",theLabel.text);
and the information is updated correctly, but the label doesn't actually update in the view. Also, updateProgress is only called AFTER everything is loaded. It updates the label THEN, which is hardly useful. Any suggestions?
The NSURLConnection is blocking the main thread (no updates will be performed on the view until it finishes).
You can perform updateProgress in the background:
[self performSelectorInBackground:#selector(updateProgress) withObject:nil]
The first line of updateProgress should be:
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc]init];
The last lines should be:
[pool release];
pool = nil;
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html
Of course, you can also perform the NSURLConnection in the background. Then you can update the label on the main thread.

UIActivityIndicator not working properly?

I have a problem regarding UIActivityIndicator. I applied [spinner startAnimating] at the IBAction on a button and then doing some process. After the process activityindicator should be stopped and then navigate to another view. But the activity indicator does not appear. When I remove the line "[spinner stopAnimating]" then the indicator appears but not at the instant button is pressed. It appears just before the other view loads, and apparently does not appear, I mean it does not appear but if we see very carefully then only it appears for an instant.
Thanx in advance for any answer.
Ole is pretty much correct, but there is a trick of you don't mind synchronous processing (often that it why you want to display the activity indicator in the first place).
First move your code that you want to process while the spinner is up to its own method. Then do
[spinner startAnimating];
[self performSelector:#selector(methodname) withObject:nil afterDelay:0];
The afterDelay:0 means on the next time through the run loop. That way the spinner gets started.
The animation will not start until your code returns control to the run loop. If your processing task blocks the main thread, the no UI updates will take place until it is finished. You should do your processing asynchronously (e.g. by starting an NSOperation).
you should run in perform selector .
for ex:
[self performSelector:#selector(animation) withObject:nil afterDelay:0]
-(void)animation
{
NSAutoreleasepool *pool = [[NSAutorepleasepool alloc]init];
[indicatorView startAnimating];
[pool release];
}
This is an old question. I leaving my answer here, so that might help someone to solve their problem.

Processing a method after the view has loaded

I have implemented a subview which is supposed to load immediately when I click a button in the parent view. After loading the subview(which is basically holding an activityindicator), the program is supposed to process a method(which gets data from a server, so takes time) in it.
However, I am unable to do it.
What happens now is, when I click the button on the parent view, it processes the method first and only after that does the subview load on screen.
Why is this so? Is there any specific functions I could use to make my method load only after the view has loaded?
I have faced the same problem and i have used NSAutoreleasePool and solved this problem. I hope it will help you.
- (void)viewDidLoad {
[self performSelectorInBackground:#selector(loadXml) withObject:nil];
}
-(void) loadXml{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString * path =#"http:www.YOUR_RSS_FEED.com";
[self parseXMLFileAtURL:path]; //(Instead of ViewDidAppear)
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
[pool drain];
}
Thanks.
A few different approaches:
If the subview has functionality as loading an image and doing more complicated stuff than just being a view, a good approach is to make it into a ViewController instead.
In the top ViewController use:
- (void) loadView {
[super loadView];
}
to set up things that need to be ready upon displaying the view.
The use:
-(void) viewDidLoad {
}
to do additional setup.
In your case it sounds as if you need to add the indicator in the loadView method, then start the retrieval of data in the viewDidLoad method.
If you are accessing web services etc. always do this on a different thread. (look into NSOperation for a good, simple way of achieving this).