6
NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"]; 
NSData *data = [NSData dataWithContentsOfURL:url]; 
imageView.image = [[[UIImage imageWithData:data];

I want to set progress bar while downloading.

Milen
  • 8,697
  • 7
  • 43
  • 57
razesh
  • 487
  • 4
  • 15
  • You might use `AFNetworking` for it, but @richy answer from this question might help http://stackoverflow.com/questions/10480815/progress-bar-while-downloading-files-ios?rq=1 if you don't want third-party libraries. – Jakub Nov 07 '13 at 09:18
  • You can show a progress bar for above code only if you run above code in a background thread and inside that background thread use a timer to check the NSData length periodically and update the progress bar value on main thread (Works only if you know the NSData length in advance otherwise you have to use Async NSURLconnection to get the exact file size). – Dinesh Nov 07 '13 at 09:23
  • Not sure what the down votes are for? BTW I'd recommend avoiding third party frameworks like AFNetworking. At least until you're comfortable writing your own networking. Even then, I avoid them. I prefer debugging my own code rather than someone else's. – Fogmeister Nov 07 '13 at 09:23
  • @Dinesh and how does he get the expected length of the data in order to set percentage completion? – Fogmeister Nov 07 '13 at 09:24

3 Answers3

12

To give a more detailed example:

in your .h file do

@interface YourClass : YourSuperclass<NSURLConnectionDataDelegate>

in your .m file do

@property (nonatomic) NSMutableData *imageData;
@property (nonatomic) NSUInteger totalBytes;
@property (nonatomic) NSUInteger receivedBytes;

And somewhere call

NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

And also implement the delegate methods

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) urlResponse;
    NSDictionary *dict = httpResponse.allHeaderFields;
    NSString *lengthString = [dict valueForKey:@"Content-Length"];
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    NSNumber *length = [formatter numberFromString:lengthString];
    self.totalBytes = length.unsignedIntegerValue;

    self.imageData = [[NSMutableData alloc] initWithCapacity:self.totalBytes];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.imageData appendData:data];
    self.receivedBytes += data.length;

    // Actual progress is self.receivedBytes / self.totalBytes
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    imageView.image = [UIImage imageWithData:self.imageData];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    //handle error
}
Marc
  • 6,051
  • 5
  • 26
  • 56
  • You're not using the correct method here. You should be using the NSURLConnectionDownloadDelegate to report progress. That is what it's for. See my Gist. – Fogmeister Nov 07 '13 at 09:44
  • 2
    I extracted this from working code.. I guess these are the correct methods. – Marc Nov 07 '13 at 10:17
  • I suppose you could use that method. The "correct" way is to use the download delegate. – Fogmeister Nov 07 '13 at 10:18
  • Honestly I don't think so. The download delegate is for NSURLConnections that where created by Newsstand Kit. In my (and your) implementation, the NSURLConnection is created manually, therefore the data delegate suits better. – Marc Nov 07 '13 at 10:23
  • 3
    Ah, maybe you're right. Dunno. I've used this before but missed the NewsStand bit. Actually you're prob right. – Fogmeister Nov 07 '13 at 10:24
  • This is a good answer, but there are two syntax errors due to misplaced brackets. 1. Add a `[` before `[NSURLConnection alloc]` 2. Remove the `[` at the beginning of the `[self.imageData =` line. I can't edit the answer as an innocent bystander because the fix is fewer than 6 characters. – Chris Ostmo Oct 12 '14 at 18:58
  • I used it in a class I had, and it works very neatly. – Septronic Dec 04 '15 at 01:53
2

You can't get progress call backs by using that method.

You need to use an NSURLConnection and NSURLConnectionDataDelegate.

The NSURLConnection then runs asynchronously and will send callbacks to its delegate.

The main ones to look at are...

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

and

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

These are all used for getting the connection to do what you're already doing.

EDIT

Actually, see Marc's answer below. It is correct.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
-2

You can use MBProgress Hud class for loading view. You can download only two classes from here :-https://github.com/jdg/MBProgressHUD After you write this code in that class which you want to load the data Example :In your viewDidLoad you write this

- (void) viewDidLoad
{
    MBProgressHud *spinner =  [MBProgressHUD showHUDAddedTo:self.view animated:YES];

        spinner.mode = MBProgressHUDModeCustomView;

        [spinner setLabelText:@"Loading....."];

        [spinner setLabelFont:[UIFont systemFontOfSize:15]];

        [spinner show:YES];

        [self performSelectorInBackground:@selector(getData) withObject:nil];
}

- (void) getData
{
     NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"]; 

        NSData *data = [NSData dataWithContentsOfURL:url]; 

        imageView.image = [[[UIImage imageWithData:data];

        [spinner hide:YES];

        [spinner removeFromSuperViewOnHide];
}
Gurpreet
  • 181
  • 6
  • This will only show a spinner though. Not a progress bar. And you can do it also with a simply Activity Indicator View – Blasco73 Sep 12 '14 at 15:17