加載網絡圖片可以說是網絡應用中必備的。如果單純的去下載圖片,而不去做多線程、緩存等技術去優化,加載圖片時的效果與用戶體驗就會很差。
一、自己實現加載圖片的方法
tips:
以下代碼用NSOperation開異步線程下載圖片,當下載完成時替換佔位圖片。
//
// XNViewController.m
// 加載網絡圖片, 普通的用NSOperation來做.
//
// Created by neng on 14-7-7.
// Copyright (c) 2014年 neng. All rights reserved.
//
#import "XNViewController.h"
#import "XNApp.h"
@interface XNViewController ()
@property (nonatomic, strong) NSArray *appList;
@property (nonatomic, strong) NSOperationQueue *queue;
@end
@implementation XNViewController
#pragma mark - 懶加載
- (NSOperationQueue *)queue {
if (!_queue) _queue = [[NSOperationQueue alloc] init];
return _queue;
}
//可抽取出來寫到模型中
- (NSArray *)appList {
if (!_appList) {
//1.加載plist到數組中
NSURL *url = [[NSBundle mainBundle] URLForResource:@"apps.plist" withExtension:nil];
NSArray *array = [NSArray arrayWithContentsOfURL:url];
//2.遍歷數組
NSMutableArray *arrayM = [NSMutableArray array];
[array enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
[arrayM addObject:[XNApp appWithDict:obj]]; //數組中存放的是字典, 轉換爲app對象後再添加到數組
}];
_appList = [arrayM copy];
}
return _appList;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight = 88;
// NSLog(@"appList-%@",_appList);
}
#pragma mark - 數據源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.appList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ID = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//用模型來填充每個cell
XNApp *app = self.appList[indexPath.row];
cell.textLabel.text = app.name; //設置文字
//設置圖像: 模型中圖像爲nil時用默認圖像,並下載圖像. 否則用模型中的內存緩存圖像.
if (!app.image) {
cell.imageView.image = [UIImage imageNamed:@"user_default"];
[self downloadImg:indexPath];
}
else {
//直接用模型中的內存緩存
cell.imageView.image = app.image;
}
// NSLog(@"cell--%p", cell);
return cell;
}
/**始終記住, 通過模型來修改顯示. 而不要試圖直接修改顯示*/
- (void)downloadImg:(NSIndexPath *)indexPath {
XNApp *app = self.appList[indexPath.row]; //取得改行對應的模型
[self.queue addOperationWithBlock: ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到圖像數據
UIImage *image = [UIImage imageWithData:imgData];
//在主線程中更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
//通過修改模型, 來修改數據
app.image = image;
//刷新指定表格行
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
}];
}
@end
二、使用第三方框架SDWebImage。(非常優秀)
#pragma mark - 數據源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.appList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ID = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//用模型來填充每個cell
XNApp *app = self.appList[indexPath.row];
cell.textLabel.text = app.name; //設置文字
// //設置圖像: 模型中圖像爲nil時用默認圖像,並下載圖像. 否則用模型中的內存緩存圖像.
// if (!cell.imageView.image) {
// cell.imageView.image = [UIImage imageNamed:@"user_default"];
//
// [self downloadImg:indexPath];
// }
// else {
// //直接用模型中的內存緩存
// cell.imageView.image = app.image;
// }
//使用SDWebImage來完成上面的功能. 針對ImageView.
//一句話, 自動實現了異步下載. 圖片本地緩存. 網絡下載. 自動設置佔位符.
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"user_default"]];
return cell;
}
/**始終記住, 通過模型來修改顯示. 而不要試圖直接修改顯示*/
//- (void)downloadImg:(NSIndexPath *)indexPath {
// XNApp *app = self.appList[indexPath.row]; //取得改行對應的模型
//
// [self.queue addOperationWithBlock: ^{
// NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到圖像數據
// UIImage *image = [UIImage imageWithData:imgData];
//
// //在主線程中更新UI
// [[NSOperationQueue mainQueue] addOperationWithBlock: ^{
// //通過修改模型, 來修改數據
// app.image = image;
// //刷新指定表格行
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
// }];
// }];
//}
@end
SDWebImage中的一些參數: