iOS Image KVO


/*

+ (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(@"请求完数据之前,我会不会执行?");

     

     */

    

    

    

    // 为什么不使用同步请求图片?

    // 原因是,同步请求图片会卡线程,在数据请求完成之前,下面的代码都不会执行。因此我们使用异步请求。

    

    // 异步请求图片 不会卡线程,请求数据 主线程中代码的执行,互不干扰。因此,使用异步请求图片,避免了数据没有请求下来之前,白屏的问题。

    

    

    // 异步请求解决了卡问题。但是如果要给1000imageView 赋值,有1000个不同的 网络地址,我们就需要把 urlrequest 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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值