仿SDWebImage多圖片下載
一、思路分析
-
無緩衝
有緩衝:優化
二、實現
- 1.抽取分類:快速獲取沙盒路徑,因為要實現緩衝嗎
// .h 檔案
#import <Foundation/Foundation.h>
@interface NSString (JP)
// 用於生成檔案在caches目錄中的路徑
- (instancetype)cacheDir;
// 用於生成檔案在document目錄中的路徑
- (instancetype)docDir;
// 用於生成檔案在tmp目錄中的路徑
- (instancetype)tmpDir;
// .m檔案
#import "NSString+JP.h"
@implementation NSString (JP)
- (instancetype)cacheDir
{
// 1.獲取caches目錄
NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 2.生成絕對路徑
return [path stringByAppendingPathComponent:[self lastPathComponent]];
}
- (instancetype)docDir
{
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
return [path stringByAppendingPathComponent:[self lastPathComponent]];
}
- (instancetype)tmpDir
{
NSString *path = NSTemporaryDirectory();
return [path stringByAppendingPathComponent:[self lastPathComponent]];
}
@end
- 2.實現
#import "ViewController.h"
#import "JPApp.h"
#import "NSString+JP.h"
@interface ViewController ()
@property (nonatomic, strong) NSArray *apps; /**< 應用程式模型陣列資訊 */
@property (nonatomic, strong) NSMutableDictionary *imageCaches; /**< 圖片記憶體快取 */
@property (nonatomic, strong) NSMutableDictionary *operations; /**< 任務快取 */
@end
@implementation ViewController
- (void)viewDidLoad{
[super viewDidLoad];
self.tableView.rowHeight = 150;
}
#pragma mark - UITableViewDatasource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.apps.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.獲取cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
// 2.設定資料
JPApp *app = self.apps[indexPath.row];
cell.textLabel.text = app.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"下載:%@", app.download];
cell.imageView.image = [UIImage imageNamed:@"abc"];
// 設定圖片
/*
存在的問題:
1.在主執行緒中下載圖片, 可能會阻塞主執行緒
2.重複下載
*/
// 1.先從記憶體快取中獲取, 如果沒有才去下載
UIImage *image = self.imageCaches[app.icon];
if (image == nil) {
// 2.再從磁碟快取中獲取, 如果沒有才去下載
NSString *filePath = [app.icon cacheDir];
__block NSData *data = [NSData dataWithContentsOfFile:filePath];
if (data == nil) {
NSLog(@"下載圖片");
/*
存在的問題:
1.重複設定
2.重複下載
*/
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 3.判斷當前圖片是否有任務正在下載
NSBlockOperation *op = self.operations[app.icon];
if (op == nil) {
// 沒有對應的下載任務
op = [NSBlockOperation blockOperationWithBlock:^{
// 開啟子執行緒下載
// 記憶體快取中沒有值, 需要下載
NSURL *url = [NSURL URLWithString:app.icon];
data = [NSData dataWithContentsOfURL:url];
if (data == nil) {
// 如果下載失敗, 應該將當前圖片對應的下載任務從快取中移除 \
以便於下次可以再次嘗試下載
[self.operations removeObjectForKey:app.icon];
return;
}
UIImage *image = [UIImage imageWithData:data];
// 將下載好的圖片快取到記憶體快取中
self.imageCaches[app.icon] = image;
// 將下載好的圖片寫入到磁碟
[data writeToFile:filePath atomically:YES];
// 回到主執行緒更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"更新UI");
// cell.imageView.image = image;
// 重新整理指定的行
// 0 / 4
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
// 從快取中將當前圖片對應的下載任務移除
[self.operations removeObjectForKey:app.icon];
}];
}];
// 先將下載任務儲存到快取中
self.operations[app.icon] = op;
// 將任務新增到佇列中
[queue addOperation:op];
}
}else
{
NSLog(@"使用磁碟快取");
NSData *data = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:data];
// 將下載好的圖片快取到記憶體快取中
self.imageCaches[app.icon] = image;
// 更新UI
cell.imageView.image = image;
}
}else
{
NSLog(@"使用記憶體快取");
// 更新UI
cell.imageView.image = image;
}
// 3.返回cell
return cell;
}
// 接收到記憶體警告
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// 釋放當前不需要使用記憶體
self.imageCaches = nil;
self.operations = nil;
self.apps = nil;
}
#pragma mark - lazy
- (NSArray *)apps
{
if (!_apps) {
// 1.從plist中載入陣列
NSString *path = [[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil];
NSArray *arr = [NSArray arrayWithContentsOfFile:path];
// 2.定義陣列儲存轉換好的模型
NSMutableArray *models = [NSMutableArray arrayWithCapacity:arr.count];
// 3.遍歷陣列中所有的字典, 將字典轉換為模型
for (NSDictionary *dict in arr) {
JPApp *app = [JPApp appWithDict:dict];
[models addObject:app];
}
_apps = [models copy];
}
return _apps;
}
- (NSMutableDictionary *)imageCaches
{
if (!_imageCaches) {
_imageCaches = [NSMutableDictionary dictionary];
}
return _imageCaches;
}
- (NSMutableDictionary *)operations
{
if (!_operations) {
_operations = [NSMutableDictionary dictionary];
}
return _operations;
}
@end
相關文章
- 獲取SDWebImage下載的圖片Web
- SDWebImage類實現圖片的下載Web
- SDWebImage載入多個圖片記憶體崩潰的問題Web記憶體
- PHP仿微信多圖片預覽上傳功能PHP
- SDWebImage載入圖片的URL是同一個(如何處理)Web
- Android 超高仿微信圖片選擇器 圖片該這麼載入Android
- 圖片下載框架概述框架
- Python 下載圖片Python
- UIWebView攔截圖片請求,SDWebImage下載快取到本地,然後從本地讀取到UIWebView中UIWebView快取
- 本地HTML中圖片下載HTML
- Android 自定義本地圖片載入庫,仿微信相簿Android地圖
- 關於SDWebImage載入高清圖片導致app崩潰的問題WebAPP
- flutter 圖片檢視,仿微信Flutter
- Swift多執行緒:使用GCD實現非同步下載圖片Swift執行緒GC非同步
- 使用httpclient下載 頁面、圖片HTTPclient
- python自動下載圖片Python
- Opencv官方樣例圖片下載OpenCV
- SDWebImage支援URL不變時更新圖片內容Web
- Swift使用SDWebImage處理遠端圖片資源SwiftWeb
- SDWebImage實現圖片展示、快取、清除快取Web快取
- TestFlight下載App,載入圖片失效。Xcode安裝App,圖片載入正常。APPXCode
- js:原生多張圖片延遲載入(圖片自己找)JS
- 谷歌、flick網站圖片 一次性下載 javaWeb專案 多執行緒下載,谷歌網站JavaWeb執行緒
- 『自定義View實戰』—— 仿ios圖示下載viewViewiOS
- 圖解SDWebImage圖解Web
- 前端實現點選下載圖片前端
- css去除圖片下多餘空白區域CSS
- 原生JS實現base64圖片下載-圖片儲存到本地JS
- iOS Swift 仿微信聊天圖片顯示iOSSwift
- 基於ThinkPHP的圖片下載網站PHP網站
- Python中scrapy下載儲存圖片Python
- Python學習筆記 - 下載圖片Python筆記
- vue點選下載圖片的實現Vue
- vue前端製作圖片,並下載(canvase)Vue前端Canvas
- lxml庫和貼吧圖片下載案例XML
- 爬蟲 Scrapy框架 爬取圖蟲圖片並下載爬蟲框架
- 高仿QQ 傳送圖片高亮HaloProgressViewView
- 圖片仿摺痕效果工具:JixiPix Fold Defy for MacMac