iOS KVO 设计模式的应用

#import "ActivityListViewController.h"

#import "ActivityListViewCell.h"

#import "Activity.h"

@interface ActivityListViewController ()

// 存放activity的数组

@property (nonatomic,strong) NSMutableArray *modelArray;

@end

@implementation ActivityListViewController

// 请求网络数据

- (void)setNetWorkData

{

// 活动网址: http://project.lanou3g.com/teacher/yihuiyun/lanouproject/activitylist.php

// 1. URL

NSURL *url = [NSURL URLWithString:@"http://project.lanou3g.com/teacher/yihuiyun/lanouproject/activitylist.php"];

// 2. request

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

// 3. connection

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

// 4. 解析数据

NSDictionary *rootDic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

// events

NSArray *array = [rootDic objectForKey:@"events"];

//  开辟空间

self.modelArray = [NSMutableArray array];

// kvc赋值

for (NSDictionary *dic in array) {

Activity *activity = [[Activity alloc] init];

[activity setValuesForKeysWithDictionary:dic];

[self.modelArray addObject:activity];

}

// 5. 刷新单元格数据

// 原因: 网络数据请求需要时间,因此 单元格创建会在数据请求完成之前执行。所以,我们在数据请求完成之后,再次给单元格赋值。

[self.tableView reloadData];

}];

}

- (void)viewDidLoad {

[super viewDidLoad];

// 调用请求网络数据

[self setNetWorkData];

// Uncomment the following line to preserve selection between presentations.

// self.clearsSelectionOnViewWillAppear = NO;

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.

// self.navigationItem.rightBarButtonItem = self.editButtonItem;

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

#warning Incomplete implementation, return the number of sections

return 1;

}

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

#warning Incomplete implementation, return the number of rows

return [self.modelArray count];

}

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

ActivityListViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell1" forIndexPath:indexPath];

// Configure the cell...

Activity *activity = self.modelArray[indexPath.row];

// 查看activity中,是否已经下载图片,如果没有,则下载

if (activity.picture == nil && activity.isDownLoading == NO) {

[activity loadImage];

// 下载图片后,给activity添加观察者

// 1. 添加观察者

[activity addObserver:self forKeyPath:@"picture" options:(NSKeyValueObservingOptionNew) context:(__bridge void * _Nullable)(indexPath)];

// arc 需要 桥接,(__bridge void *)indexPath

// mrc 里需要进行retain [indexPath retain],防止野指针

}

// 此时存在问题,当单元格第一次加载的时候,没有图片,因为,第一次加载时可能图片没有下载下来,赋值时就没有值。 当再次加载单元格时才有数据。

// 原因: 数据请求下来后,没有被及时添加到单元格上。 数据有了,但是没有赋值。

// 解决方案:使用 KVO 观察者模式,观察 activity,观察activity 的pICTure属性, tableViewController 去观察

// 1. 被观察者 activity ,

// 2. 被观察属性 picture

// 3. 观察者 self (tableViewController)

// 4. 执行操作  当图片下载下来后,执行观察方法,我们把下载下来的图片赋值给单元格。

cell.activity = activity;

return cell;

}

// 2. 实现kvo方法

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

{

// 1. 获取改变的值--获取下载后的图片

UIImage *newImage = (UIImage *)[change objectForKey:@"new"];

// 2. 获取传递过来的数据 indexPath

// 注意: 也需要强制转换,如果是arc,需要桥接

NSIndexPath *indexPath = (__bridge NSIndexPath *)context;

// 如果下载好的单元格正在被显示,我们才把图片赋值给它,否则就没有意义。如果一个没有正在显示的单元格数据,(重用队列里面的单元格)就会出现,单元格加载出来时,有别的数据。类似于,拿了一个脏盘子给你。

// 3. 获取正在显示的单元格下标数组

NSArray *array = [self.tableView indexPathsForVisibleRows];

// 4. 判断indexPath 是否正在显示,即是否在数组中

if ([array containsObject:indexPath]) {

// 说明正在显示,把下载好的图片赋值给单元格

// 获取单元格

ActivityListViewCell *cell = (ActivityListViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];

// 给单元格赋值

cell.pictureView.image = newImage;

}

// 三、 触发观察者方法

// ......

// 四、移除观察者

[object removeObserver:self forKeyPath:@"picture"];

// 补充: mrc 如果想要观察者一直观察,又不想出现内容泄露,那么,可以把移除写在 dealloc 里面。

}

时间: 2024-10-05 18:27:22

iOS KVO 设计模式的应用的相关文章

iOS KVO概述

iOS KVO概述 面试中经常会被问到:什么是KVO?这个问题既然出现概率这么大,那么我们就来详细讲一讲到底什么是KVO.下次再有面试官问你的时候,你就可以娓娓道来,以彰显高逼格 概述 问:什么是KVO? 答:KVO是Key-Value Observing的缩写.它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知.简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了. 如果你能这样回答,面试官一定不会说你错的,这就是KVO的原理.但是如果你能说出KVO

iOS 关于 设计模式 与网友讨论实录

关于 设计模式 与网友讨论实录 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 其实本篇就是想记录一下自已的一句对自已的总结,可能以前都没有意识到吧: 本图片版权归网友 杭州-老虎 所有. iO

iOS.常用设计模式.02.委托模式

WTDelegate #import <Foundation/Foundation.h> @protocol WTDelegate <NSObject> @required - (void)sleep; - (void)eat; - (void)work; @end WTPhilosopher.h #import <Foundation/Foundation.h> #import "WTDelegate.h" @interface WTPhiloso

iOS.常用设计模式.01.单例模式

使用单例模式的类: UIApplication UIAccelerometer NSUserDefaults NSNotificationCenter NSFileManager NSBundle等 Singleton.h #import <Foundation/Foundation.h> @interface Singleton : NSObject // 始终返回同一个Singleton的指针 + (Singleton *)sharedManager; @property (strong,

iOS的设计模式-KVC

关于iOS的设计模式,相信大家肯定不会陌生了,其中最常见的是MVC,也就是模型-视图-控制器模式,也是我们经常用的,这个这里就不在叙述了,这里主要讲一讲KVC这种模式,若文中有纰漏,请广大博友出来指正~~ 聊聊设计模式 虽然设计模式时时刻刻存在我们的项目工程里,但是我们却很少去注意它们,只是不自觉的去运用. 在软件设计领域,设计模式是对通用问题的可复用的解决方案.设计模式是一系列帮你写出更可理解和复用代码的模板,设计模式帮你创建松耦合的代码以便你不需要费多大力就可以改变或者替换代码中的组件. 所

KVO之IOS学习-设计模式

KVO 即Key-Value Observing  键-值观察的缩写,简单的说就是通过键来观察一个对象属性值的变化.当这个被观察的属性发生变化时,观察者就会收到通知(观察者可以是这个对象本身,也可以是其他对象). 下面来模拟KVO的实现过程: 创建一个People类,其有俩个属性name,sex -----------------------People.h文件中---------------------------- #import <Foundation/Foundation.h> @in

你真的了解iOS代理设计模式吗?

OS中消息传递方式 在iOS中有很多种消息传递方式,这里先简单介绍一下各种消息传递方式. 通知:在iOS中由通知中心进行消息接收和消息广播,是一种一对多的消息传递方式. 代理:是一种通用的设计模式,iOS中对代理支持的很好,由代理对象.委托者.协议三部分组成. block:iOS4.0中引入的一种回调方法,可以将回调处理代码直接写在block代码块中,看起来逻辑清晰代码整齐. target action:通过将对象传递到另一个类中,在另一个类中将该对象当做target的方式,来调用该对象方法,从

iOS开发指南 第8章 iOS常用设计模式 学习

设计模式是在特定场景下对特定问题的解决方案 1 单例模式 作用:解决“应用中只有一个实例”的问题,这个实例的作用是全局的,比如说是可以实现一些共享资源 方法的访问和状态的保持 实现原理:一般会封装一个静态属性,并提供静态实例的创建方法. *********** James Rumbaugh对类的定义是:类是具有相似结构.行为和关系的一组对象的描述符.类是面向对象系统中最重要的构造块.类图显示了一组类.接口.协作以及他们之间的关系. 建立类图的步骤: (1)研究分析问题领域确定系统需求. (2)确

包建强的培训课程(8):iOS与设计模式

v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} Normal 0 false 10 pt 0 2 false false false EN-US ZH-CN X-NONE $([{£¥·‘“〈<「『[[[〝﹙﹛﹝$(.[{£¥ !%),.:;>?]}¢¨°·ˇˉ