• TableView_图片异步加载 KVO


    TableView 异步下载图片

    ImageDownloader.h

    #pragma mark - 声明block

    //1,声明block

    typedef void(^Result) (UIImage *img);

    @interface ImageDownloaderViewController : UIViewController

    #pragma mark - 声明方法

    //block 做参数

    //ImageDownloader 允许外界指定URL,提供 开始下载 和 取消下载 功能,并提供delegate或block将图⽚片传递给外界。

    + (void)imageDownloaderWithUrlStr:(NSString *)urlStr result:(Result)result;

     

    ImageDownloader.m

     

    + (void)imageDownloaderWithUrlStr:(NSString *)urlStr result:( Result)result

    {

        NSURL *url = [NSURL URLWithString:urlStr];

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue new]autorelease] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

            //把请求的二进制数据 转成图片

            UIImage *image = [UIImage imageWithData:data];

            //回到主线程调用

            dispatch_sync(dispatch_get_main_queue(), ^{

                //调用block 

                result(image);

            });

        }];

    }

    TableViewController.m

     

    //加载数据

    - (void)loadDataAndShow

    {

        NSURL *url = [NSURL URLWithString:URL_NEW];

        

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        

        [request setHTTPMethod:@"GET"];

        __block NewsTableViewController *weakSelf = self;

            NSOperationQueue *queue = [[NSOperationQueue new] autorelease];

        //建立连接,

        [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

             //取大字典数据

            //从key为result的数组中 取字典

            //在此循环完成 即图片赋值完成

            for (NSDictionary *dic in dict[@"result"]) {

                //创建模型

                News *new = [News new];

               

                NSLog(@"模型创建,图片 开始下载");

                //此时 图片开始下载

                [new setValuesForKeysWithDictionary:dic];

                

                [weakSelf.allDataMutableArray addObject:new];

                [new release];

            }

            

            //回主线程

            dispatch_sync(dispatch_get_main_queue(), ^{

                //先刷新UI再拿到图片

                [weakSelf.tableView reloadData];

                NSLog(@" 刷新UI");

            });

        }];

    }

     

     

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

     

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    #warning Incomplete method implementation.

        // Return the number of rows in the section.

        return _allDataMutableArray.count;

    }

    //显示Cell

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

        NSLog(@"  显示 一个 cell");

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"new" forIndexPath:indexPath];

            // Configure the cell...

        News *new = _allDataMutableArray[indexPath.row];

            cell.textLabel.text = new.movieName;

        cell.detailTextLabel.text = new.movieId;

        //如果图片数据请求下来,就赋值显示。如果没有,就监听

        if (new.imageData != nil) {

            cell.imageView.image = new.imageData;

        }else{

                 NSLog(@" 图片没请求下来---》》》监听 ");

            //KVO (1,注册监听)设置监听图片数据

            //new 被监听

            //self  监听者

            //keypath  监听属性

            //options   监听旧值 还是 新值

            //控制器 观察 -》模型(在控制器中观察)

            [new addObserver:self forKeyPath:@"imageData" options:NSKeyValueObservingOptionNew context:indexPath];

            }

        return cell;

    }

     

    #pragma mark - (2,实现回调方法)  KVO 监听被执行的方法,对象属性变化,即调用

    //tableView 通过KVO观察 下载数据 及时更新页面

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

    {

        //判断标志

        if ([keyPath isEqualToString:@"imageData"]) {

            //1, 获取新图片数据

            UIImage *newImageData = change[NSKeyValueChangeNewKey];

            

            //2, 获取cell

            NSIndexPath *indexPath = (NSIndexPath *)context;

            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

            cell.imageView.image = newImageData;

            //3, 刷新当前行

            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

            //4,取消监听

            [object removeObserver:self forKeyPath:keyPath];

            

             NSLog(@"(监听值变化)拿到图片了。。。。。。");

        }

    }

    //模型.h

    @interface News : NSObject

    @property(nonatomic,copy)NSString *movieId;

    @property(nonatomic,copy)NSString *movieName;

    @property(nonatomic,copy)NSString *pic_url;

    //Model类注意事项:

    //1、除了包含必要的数据外,还要包含⼀一个ImageDownloader对象。

    //2、包含⼀一个image。

    //3、包含⼀一个图⽚片是否正在下载的BOOL值。(⽤用于判断是否需要开始 下载)

    @property(nonatomic,retain) UIImage *imageData;

     

    //模型.m

     

    #pragma mark - 重写pic_url 的 setter

    //为了能正确显示图片,Model类应该提供图片获取功能(Model通过 ImageDownloader下载图片,供cell使用)

    - (void)setPic_url:(NSString *)pic_url

    {

        if (_pic_url != pic_url) {

            [_pic_url release];

            _pic_url = [pic_url retain];

            

            //

            //使用block 异步加载图片

            __block News *weakNews = self;

            [ImageDownloaderViewController imageDownloaderWithUrlStr:self.pic_url result:^(UIImage *img) {

                //将block 显示到imageView上

                //在这使用,就在这实现(模型中实现block)

                weakNews.imageData = img;

                NSLog(@"--------------拿到图片,赋值显示 NEws");

            }];

        }

    }

     

  • 相关阅读:
    python文件处理
    pycharm基础
    lvs集群DR模式,负载均衡
    JSP动作元素<jsp:include>和<jsp:param>的搭配使用
    Mybatis的动态SQL讲解
    hibernate多对多查询
    Hibernate配置文件与映射文件详解
    maven的不同版本下载及环境配置
    二级联动,例:根据省份选择市区
    关于JSP页面的静态包含和动态包含
  • 原文地址:https://www.cnblogs.com/iOS-mt/p/4180812.html
Copyright © 2020-2023  润新知