/*
+ (UIImage *)requestImageWithURL:(NSString *)urlString
{
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url ];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
UIImage *image = [UIImage imageWithData:data];
return image;
}];
UIImage *image = [UIImage imageWithData:data];
return image;
}
*/
// 点击按钮给 model 赋值
- (IBAction)button:(id)sender {
// 给perosn.name 赋值
self.person.name = self.tf.text;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 创建UIImage的方法
// 1. 通过imageNamed: imageWithContentOfFile: 加载本地图片
// 2. 通过 imageWithData: 获取网络图片
// 练习1: 给imageView 通过网络数据添加图片
// 图片url链接:http://img3.douban.com/view/event_poster/median/public/10f53a2ad8b38c5.jpg
/*
NSURL *url = [NSURL URLWithString:@"http://img3.douban.com/view/event_poster/median/public/10f53a2ad8b38c5.jpg"];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url ];
// NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"请求到数据");
_pictureView.image = [UIImage imageWithData:data];
}];
NSLog(@"请求完数据之前,我会不会执行?");
*/
// 为什么不使用同步请求图片?
// 原因是,同步请求图片会卡线程,在数据请求完成之前,下面的代码都不会执行。因此我们使用异步请求。
// 异步请求图片 不会卡线程,请求数据 和 主线程中代码的执行,互不干扰。因此,使用异步请求图片,避免了数据没有请求下来之前,白屏的问题。
// 异步请求解决了卡问题。但是如果要给1000个imageView 赋值,有1000个不同的 网络地址,我们就需要把 url,request connection ,的过程写1000遍。这显然不符合 我们编程思想。因此考虑写一个类,把网络请求给封装起来。
// ImageDownloader
// 使用封装的网络请求方法,给imageView.image 赋值
// [ImageDownloader imageWithURLString:@"http://img3.douban.com/view/event_poster/median/public/10f53a2ad8b38c5.jpg" completation:^(UIImage *image) {
//
// self.pictureView.image = image;
//
// }];
// KVO 设计模式
// KVO 设计模式为观察者模式。通常用于 控制层 与 模型层的通讯,一旦model 的值发生变化,则让controller 执行观察者方法,注意:该方法为固定方法。
// A _观察_> B, B发生变化, A执行方法
// kvo 步骤:
// 1. 给 被观察者,设置观察者,并且指定,被观察的键值。
// 2. 观察者 实现观察方法
// 3. 当 被观察者,键值发生改变, 观察者执行观察方法
// 3. 被观察者 移除 观察者
// 需求: 通过 textField 给 self.person.name 赋值,一旦person.name 发生变化,执行观察者方法,改变颜色。
// 1. 添加观察者,设置被观察键值
self.person = [[Person alloc] init];
// 参数1. 观察者
// 参数2. 被观察的键值名称
// 参数3. 观察模式,通常我们使用 new,以便获取改变后的值。
// 参数4. 传递给观者方法的参数,如果没有,填nil
[self.person addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
// Do any additional setup after loading the view, typically from a nib.
}
// 2. 实现观察者方法
// 参数1. keyPath 被观察的键值名称
// 参数2. object 被观察者
// 参数3. change 发生改变的值,存储在字典里面
// 参数4. context 传递过来的参数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
// 获取改变后的值
NSString *new = [change objectForKey:@"new"];
// 改变前的值
NSString *old = [change objectForKey:@"old"];
// isEqual 不一样才执行
if ( ![new isEqual:old]) {
// 3. 执行观察者方法
// 当person.name 发生改变后,自动调用该方法
self.view.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
// 4. 移除观察者
// [object removeObserver:self forKeyPath:@"name"];
}
}
@end
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
// void (^completation)(UIImage *image);
typedef void(^Comletation)(UIImage *image); // 具有一个image类型参数,返回值为void 的block类型,类型名为Completation
@interface ImageDownloader : NSObject
// 图片下载类,提供了下载图片的方法,其内部封装了 网络请求。
// 思考: 该方法,如要外界传递的什么参数? 需要返回给外界什么参数? 何时返回?
// 参数: 外界给定的 url地址,
// 参数: 传递给外界请求下来的数据,可以是data ,也可以对data转化为image返回,
// 何时返回? 数据请求完成后返回
// 怎么返回? 因为我们的需求具有依赖关系,必须数据请求下来后才返回,因此不能够使用 方法返回值返回,而是使用block 作为参数,当数据请求下来后, 执行该 block,返回数据。
// 使用urlString,请求数据,请求完成后,执行block,给外界赋值。
+ (void)imageWithURLString:(NSString *)urlstring completation:(Comletation )completaion;
@end
#import "ImageDownloader.h"
@implementation ImageDownloader
+ (void)imageWithURLString:(NSString *)urlstring completation:(Comletation )completaion
{
// 根据urlString 进行网络请求
// 1. url
NSURL *url = [NSURL URLWithString:urlstring];
// 2. request
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
// 3. 异步网络请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// 4. 数据请求完成后,给外界赋值,执行completation();
UIImage *image = [UIImage imageWithData:data];
// 执行block 返回数据给外界
completaion(image);
}];
}
@end