How to write a dowloader class for updating downlo

2019-08-31 18:04发布

问题:

Here is my actual issue, as some suggested I want to write a class for handling the multiple download progress in a UITableView. I have no idea how to write a class for this, can somebody help with some tips or ideas?

回答1:

The group to look at is NSURLRequest and NSURLConnection. The former let's you specify the request (URL, http method, params, etc) and the latter runs it.

Since you want to update status as it goes (I answered a sketch of this in your other question, I think), you'll need to implement the NSURLConnectionDelegate protocol that hands over chunks of data as it arrives from the connection. If you know how much data to expect, you can use the amount received to calculate a downloadProgress float as I suggested earlier:

float downloadProgress = [responseData length] / bytesExpected;

Here's some nice looking example code in SO. You can extend for multiple connections like this...

MyLoader.m

@interface MyLoader ()
@property (strong, nonatomic) NSMutableDictionary *connections;
@end

@implementation MyLoader
@synthesize connections=_connections;  // add a lazy initializer for this, not shown

// make it a singleton
+ (MyLoader *)sharedInstance {

    @synchronized(self) {
        if (!_sharedInstance) {
            _sharedInstance = [[MyLoader alloc] init];
        }
    }
    return _sharedInstance;
}

// you can add a friendlier one that builds the request given a URL, etc.
- (void)startConnectionWithRequest:(NSURLRequest *)request {

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSMutableData *responseData = [[NSMutableData alloc] init];
    [self.connections setObject:responseData forKey:connection];
}

// now all the delegate methods can be of this form.  just like the typical, except they begin with a lookup of the connection and it's associated state
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    NSMutableData *responseData = [self.connections objectForKey:connection];
    [responseData appendData:data];

    // to help you with the UI question you asked earlier, this is where
    // you can announce that download progress is being made
    NSNumber *bytesSoFar = [NSNumber numberWithInt:[responseData length]];
    NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
        [connection URL], @"url", bytesSoFar, @"bytesSoFar", nil];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"MyDownloaderDidRecieveData"
        object:self userInfo:userInfo];

    // the url should let you match this connection to the database object in
    // your view controller.  if not, you could pass that db object in when you
    // start the connection, hang onto it (in the connections dictionary) and
    // provide it in userInfo when you post progress
}


回答2:

I wrote this library to do exactly that. You can checkout the implementation in the github repo.