Multi-threaded Multi-image download 2. multi-threaded image download
The final demonstration is as follows:
This is a multi-threaded download and storage of images. Considering the download failure, the placeholder image problem occurs (the first one is the image that fails to be downloaded)
Let's talk about the code. Because some parts are the same as the previous one, only the uploaded parts are different.
Still in ViewController. m
1.
@ Interface ViewController () // all data @ property (nonatomic, strong) NSArray * apps; // memory cache image @ property (nonatomic, strong) NSMutableDictionary * imgCache; /** all operations */@ property (nonatomic, strong) NSMutableDictionary * operations;/** queue object */@ property (nonatomic, strong) NSOperationQueue * queue; @ end
The first two are consistent with the previous
Operations is a dictionary used to store the thread operations for downloading images. It is mainly used to prevent repeated downloads.
Queue is the queue used when multithreading is used.
2.
-(NSOperationQueue *) queue {if (! _ Queue) {_ queue = [[NSOperationQueue alloc] init]; // maximum concurrency _ queue. maxConcurrentOperationCount = 3;} return _ queue ;}
Initialize the queue and control a maximum of three sub-threads.
3.
-(UITableViewCell *) tableView :( UITableView *) tableView cellForRowAtIndexPath :( NSIndexPath *) indexPath {static NSString * ID = @ "app"; UITableViewCell * cell = [tableView metadata: ID]; DDZApp * app = self. apps [indexPath. row]; cell. textLabel. text = app. name; cell. detailTextLabel. text = app. download; // retrieve the image UIImage * image = self from the memory first. imgCache [app. icon]; if (image) {cell. imageView. image = image;} else {// no image in memory // write the image file data to the sandbox NSString * cachesPath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES) firstObject]; // obtain the file name NSString * filename = [app. icon lastPathComponent]; // calculate the full path of the file NSString * file = [cachesPath stringByAppendingPathComponent: filename]; // load the file data in the sandbox NSData * data = [NSData dataWithContentsOfFile: file]; // determine whether there is any image in the sandbox if (data) {// directly load the image UIImage * image = [UIImage imageWithData: data]; cell. imageView. image = image; // save it to the dictionary (memory) self. imgCache [app. icon] = image;} else {// download image // placeholder image cell. imageView. image = [UIImage imageNamed: @ "place.jpg"]; // first, check whether a download task exists. // after loading fails, you can repeat downloading NSOperation * operation = self. operations [app. icon]; if (operation = nil) {// This image does not have a download task operation = [NSBlockOperation blockOperationWithBlock: ^ {NSData * data = [NSData dataWithContentsOfURL: [NSURL URLWithString: app. icon]; // data loading failed if (data = nil) {// remove operation [self. operations removeObjectForKey: app. icon]; return;} UIImage * image = [UIImage imageWithData: data]; // save it to the memory self. imgCache [app. icon] = image; // return to the main thread to display the image [[NSOperationQueue mainQueue] addOperationWithBlock: ^ {// duplicate placeholder problems may occur. // cell. imageView. image = image; // you can find the row where the image is located. [tableView reloadRowsAtIndexPaths: @ [indexPath] withRowAnimation: UITableViewRowAnimationNone];}]; // write image data to the sandbox [data writeToFile: file atomically: YES]; // remove operation [self. operations removeObjectForKey: app. icon];}]; // Add to the download queue [self. queue addOperation: operation]; // Add it to the dictionary self. operations [app. icon] = operation ;}}return cell ;}View Code
This data binding method has a lot of content, because many details are taken into account, but the logic is similar to the previous one.
Next time, draw a detailed flowchart ~