异步下载图片
图片下载是iOS开发中常用的功能,但系统并未提供图片下载类。
为了便于后续使用,可以将图片下载封装到一个类里面 (ImageDownloader)。
ImageDownloader 允许外界指定URL,提供开始下载和取消下载功能,并提供delegate或block将图片传递给外界。
创建ImageDownLoader类
新建工程,创建根视图控制器
// 在AppDelegate中
RootViewController *rootVC = [[RootViewController alloc] init];
self.window.rootViewController = rootVC;
[rootVC release];
创建ImageDownLoader类继承于NSObject
// ImageDownLoader.h中
// 创建一个协议
@protocol ImageDownLoaderDelegate <NSObject>
// 请求成功
- (void)imageDownLoadSucceedWithData:(NSData *)data;
// 请求失败
- (void)imageDownLoadFailedWithError:(NSError *)error;
@end
@interface ImageDownLoader : NSObject
// 链接
@property (nonatomic, retain) NSMutableData *receiveData;
// data
@property (nonatomic, retain) NSURLConnection *connection;
// 声明代理对象
@property (nonatomic, assign) id<ImageDownLoaderDelegate> delegate;
// 初始化方法(需要写 请求中 可能用到的参数--网址)
- (instancetype)initWithUrl:(NSString *)url delegete:(id<ImageDownLoaderDelegate>)delegate;
// 声明开始的方法
- (void)imageDownLoadStart;
// 终止方法
- (void)imageDownLoadCancel;
// ImageDownLoader.m中
// 没有延展,可以新建一个
@interface ImageDownLoader () <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@end
@implementation ImageDownLoader
- (void)dealloc
{
[_connection release];
[_receiveData release];
[super dealloc];
}
// 初始化
- (instancetype)initWithUrl:(NSString *)url delegete:(id<ImageDownLoaderDelegate>)delegate
{
self = [super init];
if (self) {
// 创建网址对象
NSURL *newNrl = [NSURL URLWithString:url];
// 创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:newNrl cachePolicy:(NSURLRequestUseProtocolCachePolicy) timeoutInterval:10];
[request setHTTPMethod:@"Get"];
// 创建链接
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
// [self.connection start];
// 设置代理
self.delegate = delegate;
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.receiveData = [NSMutableData data];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.receiveData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 图片请求完成
if (_delegate != nil && [_delegate respondsToSelector:@selector(imageDownLoadSucceedWithData:)]) {
// 代理调用协议中的方法
[_delegate imageDownLoadSucceedWithData:self.receiveData];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if (_delegate != nil && [_delegate respondsToSelector:@selector(imageDownLoadFailedWithError:)]) {
[_delegate imageDownLoadFailedWithError:error];
}
}
// 声明开始的方法
- (void)imageDownLoadStart
{
[self.connection start];
}
// 终止方法
- (void)imageDownLoadCancel
{
[self.connection cancel];
}
在RootViewController中调用ImageDownLoader类实现方法
@interface RootViewController () <ImageDownLoaderDelegate>
@property (nonatomic, retain) UIImageView *imageV;
@property (nonatomic, retain) ImageDownLoader *imageDL;
@end
@implementation RootViewController
- (void)dealloc
{
// 当页面被销毁时 终止请求
[_imageDL imageDownLoadCancel];
[_imageDL release];
[_imageV release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.imageV = [[[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
self.imageV.backgroundColor = [UIColor orangeColor];
[self.view addSubview:self.imageV];
// 创建请求对象
self.imageDL = [[ImageDownLoader alloc] initWithUrl:@"http://img3.douban.com/view/event_poster/median/public/10f53a2ad8b38c5.jpg" delegete:self];
// 开始请求
// [self.imageDL imageDownLoadStart];
[self.imageDL release];
}
// 实现协议中的方法
- (void)imageDownLoadSucceedWithData:(NSData *)data
{
self.imageV.image = [UIImage imageWithData:data];
// NSLog(@"%@", data);
}
- (void)imageDownLoadFailedWithError:(NSError *)error
{
NSLog(@"%@", error);
}
UITableView中图片的异步下载
UITableView的重用机制,让我们能用很少的cell来呈现很多的内容 (cell和model的数量不统一)。
为了能正确显示图片,Model类应该提供图片获取功能(Model通过 ImageDownloader下载图片,供cell使用)。
Model类注意事项:
1、除了包含必要的数据外,还要包含一个ImageDownloader对象。
2、包含一个image。
3、包含一个图片是否正在下载的BOOL值。(用于判断是否需要开始 下载)
Cell注意事项:
根据Model信息,做页面显示。
KVO
KVO:(Key-Value-Observer)键值观察者,是观察者设计模式的一种具体实现。
KVO触发机制:一个对象(观察者),监测另一对象(被观察者)的某属性是否发生变化,若被监测的属性发生的更改,会触发观察者的一个方法(方法名固定,类似代理方法)
##KVO使用步骤:
1、注册观察者(为被观察者指定观察者以及被观察属性)
2、实现回调方法
3、触发回调方法(被观察属性发生更改)
4、移除观察者
实现步骤:
创建新工程,添加根视图控制器
添加一个Man类继承于NSObject,创建一个属性用于监测
@interface Man : NSObject
// 钱
@property (nonatomic, retain) NSString *money;
@end
在根视图控制器中使用KVO监测属性的变化
“`
@property (nonatomic, retain) Man *man;
@end
@implementation RootViewController
(void)viewDidLoad {
[super viewDidLoad];UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)];
button.frame = CGRectMake(100, 100, 150, 50);
button.backgroundColor = [UIColor blackColor];
[button setTitle:@”点我” forState:(UIControlStateNormal)];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:(UIControlEventTouchUpInside)];
[self.view addSubview:button];/*
KVO 键值观察者
观察model中某一属性 值的变化
如果 这个属性的值发生了变化 会触发一个方法明确:
1.观察者 (控制器 触发一个方法 – 改变视图的颜色)
2.被观察者(man)
3.观察的属性(对象中的 money这个属性)控制器作为观察者 去观察 model(被观察者)中的一个属性 值的变化 会触发一个方法 (改变视图的)
观察者(C) 被观察者(Model) Model发生变化 去改变 (V)视图
*/// 创建一个对象
self.man = [[Man alloc] init];
self.man.money = @”1w”;// 添加一个观察者
// 被观察者 man
// Observer 填观察者 self
// NSKeyValueObservingOptionNew 新值
// NSKeyValueObservingOptionOld 旧值
// context 携带参数
[self.man addObserver:self forKeyPath:@”money” options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@”