views:

365

answers:

2

Hi people,

I am downloading an mp3 using NSData dataWithContentsOfURL:url. This takes a while and while the file is downloading the application hangs. I want to handle well and ideal would like to show the download progress but can't find methods for this.

It is in a UIViewController and I have made a first attempt by putting in a UIActivityIndicatorView and start it spinning before I start the download, then stop it spinning after but nothing appears.

So my question really is please could someone tell me what the best way to handle this is? Thanks so much

+2  A: 

Nothing will appear because your main thread is blocked doing the download, and the main thread is where UI updates occur.

You should use NSUrlConnection to download asynchronously and implement the delegate methods to start/stop your spinner.

Alternatively if you want to stick with NSData's dataWithContentsOfURL:url you should do this on a separate thread and update the spinner on the main thread before and after you call it.

Mike Weller
And use the status bar activityIndicator rather than a big obtrusive spinner; making the user wait when not completely essential is poor UX.
Paul Lynch
Cheers mate NSUrlconnection is exactly what i wanted! have got it working with a uiprogress view
padatronic
+1  A: 

You can achieve this while still using synchronous methods, but you need to give the run loop a chance to start animating the activity indicator before you start the download.

You can achieve this by using either performSelector:withObject:afterDelay: with delay 0 to put a run loop between your animation start and the download, or (worse style, more risky) you can directly invoke the run loop within your code.

Sample code:

- (void)loadPart1 {
  activityIndicator = [[[UIActivityIndicatorView alloc]
                        initWithActivityIndicatorStyle:UIA...StyleGray]
                       autorelease];
  activityIndicator.frame = myFrame;
  [self.view addSubview:activityIndicator];
  [activityIndicator startAnimating];
  [self performSelector:@selector(loadPart2) withObject:nil afterDelay:0];
}

- (void)loadPart2 {
  [NSURLConnection sendSynchronousRequest:request returningResponse:&response
                                    error:&error];
  [activityIndicator stopAnimating];
}

More details here: http://bynomial.com/blog/?p=15 (scroll down to Solution 1 or Solution 2).

Tyler