您的位置:首页 > 产品设计 > UI/UE

UI-KVO设计模式Demo

2015-08-18 19:57 435 查看
在这个Demo里面写了四个类:一个控制器类、一个操控数据类(即整理数据)、一个下载数据类、一个model类

在这里我用的数据路径是:
http://open.qyer.com/qyer/recommands/index?app_installtime=1427248095&client_id=qyer_ios&client_secret=cd254439208ab658ddf9&count=20&lat=40.02921998351221&lon=116.33752653006&page=1&track_app_channel=App%2520Store&track_app_version=6.1&track_device_info=iPhone%25204S&track_deviceid=47A7918C-4978-4091-B876-D0A2AE43AABB&track_os=ios%25207.1.2&v=1
//

// AppDelegate.m

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import "AppDelegate.h"

#import "RootViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions {

// Override point for customization after application launch.

self.window = [[UIWindow
alloc] initWithFrame:[[UIScreen
mainScreen] bounds]];

// Override point for customization after application launch.

self.window.backgroundColor = [UIColor
whiteColor];

[self.window
makeKeyAndVisible];



RootViewController *rootVC = [[RootViewController
alloc]
init];

self.window.rootViewController = rootVC;
[rootVC
release];



return
YES;
}

控制器类:

//

// RootViewController.h

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface RootViewController :UIViewController

@end

//

// RootViewController.m

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import "RootViewController.h"

#import "ItemHandle.h"

#import "ItemModel.h"

@interface
RootViewController ()<UITableViewDataSource,UITableViewDelegate,ItemHandleDelegate>

@property (nonatomic ,retain)UITableView *tableView;

//准备一个网络请求类的对象

@property (nonatomic ,retain)ItemHandle *itemHandle;

//tableView准备一个数组接收数据源

@property (nonatomic ,retain)NSMutableArray *dataArray;

@end

@implementation RootViewController

- (void)viewDidLoad {

[superviewDidLoad];

// Do any additional setup after loading the view.


self.tableView = [[UITableViewalloc]
initWithFrame:self.view.frame];



self.tableView.backgroundColor = [UIColorbrownColor];


[self.viewaddSubview:self.tableView];



//给tableView设置代理
self.tableView.dataSource =self;
self.tableView.delegate =self;


[self.tableViewrelease];



//调用网络请求类itemHandle让该类去做网络请求
而自己只等着代理方法的回调拿到数据就行

self.itemHandle = [ItemHandleitemHandleWithUrlString:@"http://open.qyer.com/qyer/recommands/index?app_installtime=1427248095&client_id=qyer_ios&client_secret=cd254439208ab658ddf9&count=20&lat=40.02921998351221&lon=116.33752653006&page=1&track_app_channel=App%2520Store&track_app_version=6.1&track_device_info=iPhone%25204S&track_deviceid=47A7918C-4978-4091-B876-D0A2AE43AABB&track_os=ios%25207.1.2&v=1"andDelegate:self];



//开始启动网络连接

[self.itemHandlestartDownloader];




}

#pragma mark - 网络请求类的代理的方法
- (void)itemHandle:(ItemHandle *)handle didFinishLoadingItems:(NSMutableArray
*)itemsArray
{

//一旦达到所有的model就要刷新界面


self.dataArray = itemsArray;



[self.tableViewreloadData];




}

#pragma mark -实现有协议方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

return
self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static
NSString *cellID =@"cellID";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:cellID];
if (!cell) {

cell = [[UITableViewCellalloc ]
initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:cellID];


}

// cell.textLabel.text = @"测试数据";

//取出model
ItemModel *model =
self.dataArray[indexPath.row];



//cell显示数据
cell.textLabel.text = model.title;

cell.textLabel.numberOfLines =0;

// cell.detailTextLabel.text = ;
if (model.picImage ==nil) {

//1下载之前先显示一张默认的图片下载完成之后再来更新该cell
cell.imageView.image = [UIImageimageNamed:@"6"];



//2给model的picImage属性添加观察者一旦该属性拿到新的图片就触发观察者方法

[model addObserver:selfforKeyPath:@"picImage"options:NSKeyValueObservingOptionNewcontext:indexPath];



//3开始下载图片
[modelloadItemImage];




}else {
//直接显示
cell.imageView.image = model.picImage;
}


return cell;
}

#pragma mark - 观察者的方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context
{

//baindexpath传进来的主要原因

//下载完成之后检查该indexPath是否属于正在显示的cell

//如果是就刷新cell.imageView

//如果不是什么也不做
重用cell时候会根性给 indexPath



//context indexPath

//object
监听者对象model

//change
包含了新下载的image对象



//先拿到indexPath
NSIndexPath *indexPath = (NSIndexPath *)context;



//拿到iimage对象
UIImage *image = change[@"new"];



//拿到当前界面所有显示的cell的indexPath
NSArray *indexPathsArray = [self.tableViewindexPathsForVisibleRows];



//判断要更新的cell的indexpath是否在显示列表里面
if ([indexPathsArray
containsObject:indexPath]) {

//取出该cell

// UITableViewCell *cell = [self tableView:self.tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *cell = [self.tableViewcellForRowAtIndexPath:indexPath];
cell.imageView.image = image;


}

//移出监听者

[object removeObserver:selfforKeyPath:@"picImage"context:indexPath];


}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath
*)indexPath
{
return
120;
}
- (void)didReceiveMemoryWarning {

[superdidReceiveMemoryWarning];

// Dispose of any resources that can be recreated.
}
- (void)dealloc
{

[_dataArray
release];

[_itemHandle
release];

[_tableView
release];
[superdealloc];
}

/*

#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

// Get the new view controller using [segue destinationViewController].

// Pass the selected object to the new view controller.

}

*/

@end

操控数据类

//

// ItemHandle.h

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import <Foundation/Foundation.h>

//协议
告诉代理对象 items 已经下载好让代理拿着用

@class ItemHandle;
@protocol ItemHandleDelegate <NSObject>

-(void)itemHandle:(ItemHandle *)handle didFinishLoadingItems:(NSMutableArray
*)itemsArray;

@end

//用来操作数据的类
@interface ItemHandle :NSObject

//准备一个代理棒棒

@property (nonatomic ,assign)id<ItemHandleDelegate>delegate;

//准备一个urlString

@property (nonatomic ,retain)NSString *urlString;

//声明便利构造器
+ (ItemHandle *)itemHandleWithUrlString:(NSString *)urlString andDelegate:(id<ItemHandleDelegate>)delegate;

//开始请求数据的方法
- (void)startDownloader;

//quxia哦下载
- (void)cancelConnection;

@end

//

// ItemHandle.m

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import "ItemHandle.h"

#import "ItemModel.h"

@interface
ItemHandle()<NSURLConnectionDataDelegate>

//创建连接对象

@property (nonatomic ,retain)NSURLConnection *connection;

//准备数据

@property (nonatomic ,retain)NSMutableData *allData;

@end

@implementation ItemHandle

#pragma mark - 自己为遍历构造器准备一个带有地址和代理对象的初始化方法
- (instancetype)initWithUrlString:(NSString *)urlString andDelegate:(id<ItemHandleDelegate>)delegate
{
self = [superinit];
if (self) {
self.urlString = urlString;
self.delegate = delegate;
}

return
self;


}

#pragma mark - 开始下载
- (void)startDownloader
{

//拿到URL地址

NSString *urlstring = [self.urlStringstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];



//创建url对象
NSURL *url = [NSURLURLWithString:urlstring];



//创建请求对象
NSURLRequest *request = [[NSURLRequestalloc]
initWithURL:url];



//创建连接

self.connection = [NSURLConnectionconnectionWithRequest:request
delegate:self];


}

#pragma mark - 取消lian接方法
-(void)cancelConnection
{

[self.connectioncancel];

self.connection =nil;


}

#pragma mark - connection的代理
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
*)response
{
NSLog(@"收到回应");

//初始化数据data

self.allData = [NSMutableDatadata];

//收到数据


}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData
*)data
{
NSLog(@"收到数据");
[self.allDataappendData:data];
}

#pragma mark - 链接结束
请求完成
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"请求完成");

//解析数据

//准备一个数组封装model

NSMutableArray *modelArray = [NSMutableArrayarray];

//调用解析数据方法并将数据扔到数组里面

[selfparserJsonDataWithArray:modelArray];





//告诉代理对象 请求完成
数据可以使用
if (_delegate && [_delegaterespondsToSelector:@selector(itemHandle:didFinishLoadingItems:)])
{
//实现

[_delegateitemHandle:selfdidFinishLoadingItems:modelArray];


}
}

#pragma mark - 解析数据方法
- (void)parserJsonDataWithArray:(NSMutableArray *)modelArray
{

//data->string
数据嵌套类型: 字典-》字典-》数组-》字典

// NSString *dataString = [[NSString alloc] initWithData:self.allData encoding:NSUTF8StringEncoding];

// NSLog(@"%@",dataString);

//开始解析数据

NSDictionary *dic = [NSJSONSerializationJSONObjectWithData:self.allDataoptions:NSJSONReadingMutableContainerserror:nil];

// NSLog(@"%@",dic);

//去data字典
NSDictionary *dataDic = dic[@"data"];

//取数组discount
NSArray *dataArray = dataDic[@"discount"];

// NSLog(@"%@",dataArray);

//封装model
for (NSDictionary *miniDicin dataArray) {
ItemModel *model = [ItemModelitemModelWithDictionary:miniDic];



//把model撞到数组中去
[modelArrayaddObject:model];
}


}

+ (ItemHandle *)itemHandleWithUrlString:(NSString *)urlString andDelegate:(id<ItemHandleDelegate>)delegate
{


ItemHandle *itemHandle = [[ItemHandlealloc]
initWithUrlString:urlStringandDelegate:delegate];

//有对象之后就开始请求数据(因为已经有了URL数据)


return [itemHandle
autorelease];


}

- (void)dealloc
{

[_connection
release];
[_allDatarelease];

_delegate =
nil;

[_urlString
release];
[superdealloc];


}

@end

下载数据类:

//

// ImageDownLoader.h

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

@class ImageDownLoader;

@protocol imageDownLoaderDelegate <NSObject>

//下载成功的代理方法
- (void)imageDownLoader:(ImageDownLoader *)imageDownLoader downLoadSuccessWithImage:(UIImage
*)image;

//下载失败的代理方法
- (void)imageDownLoader:(ImageDownLoader *)imageDownLoader failedWithError:(NSError
*)error;

@end

@interface ImageDownLoader :NSObject

//代理棒棒

@property (nonatomic ,assign)id<imageDownLoaderDelegate>delegate;

//下载地址

@property (nonatomic ,retain)NSString *urlString;

- (instancetype)initWithUrlString:(NSString *)urlString andDelegate:(id<imageDownLoaderDelegate>)delegate;

//开始下载
-(void)startDownLoader;

//取消下载
- (void)cancelDownLoader;

@end

//

// ImageDownLoader.m

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import "ImageDownLoader.h"

@interface
ImageDownLoader ()<NSURLConnectionDataDelegate>

@property (nonatomic ,retain)NSMutableData *allData;

@property (nonatomic ,retain)NSURLConnection *connection;

@end
@implementation ImageDownLoader

#pragma mark - 实现NSURLConnectionDataDelegate协议方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
*)response
{
NSLog(@"收到响应");

self.allData = [NSMutableDatadata];


}

#pragma mark - 链接成功
接收数据
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData
*)data
{

NSLog(@"链接接收数据
图片下载");
[self.allDataappendData:data];


}

#pragma mark - 链接结束
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"图片下载结束");

//两件事

//1、把该图片数据缓存下次就不用下载
NSString *documentPath = [self getPath];



//拿到图片的name
NSString *imageName = [self.urlString stringByReplacingOccurrencesOfString:@"/" withString:@"_"];



//图片的整个换粗你路径
NSString *filePath = [documentPath stringByAppendingPathComponent:imageName];



//缓存到文件中
[self.allData writeToFile:filePath atomically:YES];



//2、告诉代理拿到图片

//图片对象
UIImage *image = [UIImage imageWithData:self.allData];
if (_delegate && [_delegate respondsToSelector:@selector(imageDownLoader:downLoadSuccessWithImage:)]) {
[_delegate imageDownLoader:self downLoadSuccessWithImage:image];
}


}

#pragma mark - 链接失败
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"出错");

//告诉代理请求失败

//先判断代理是否存在再告诉代理请求失败
if (_delegate && [_delegate respondsToSelector:@selector(imageDownLoader:failedWithError:)]) {
[_delegate imageDownLoader:self failedWithError:error];
}
}

#pragma mark - 初始化
- (instancetype)initWithUrlString:(NSString *)urlString andDelegate:(id<imageDownLoaderDelegate>)delegate
{
self = [super init];
if (self) {
self.urlString = urlString ;
self.delegate = delegate;
}
[self startDownLoader];

return
self;


}

#pragma mark - 开始下载方法
- (void)startDownLoader
{
if (self.urlString.length ==0) {
NSLog(@"地址都是错的,不能下载图片");
}else {



//正在下载图片之前先去缓存里面看看是否有该图片

//如果没有就下载,如果有就直接拿来并告诉代理拿到图片
NSLog(@"开始下砸");

//获得图片name
NSString *imageName = [self.urlString stringByReplacingOccurrencesOfString:@"/" withString:@"_"];


//获得文件地址
NSString *filePath = [[self getPath] stringByAppendingPathComponent:imageName];



//创建文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath]) {

//如果有缓存不用
下载 直接告诉代理对象拿到图片
if (_delegate && [_delegate respondsToSelector:@selector(imageDownLoader:downLoadSuccessWithImage:)])
{


//创建image对象
UIImage *image = [UIImage imageWithContentsOfFile:filePath];


//把image对象传给代理
[_delegate imageDownLoader:self downLoadSuccessWithImage:image];
}


}else {

//缓存中没有该图片那就开始下载
NSLog(@"开始下载图片");
//创建url对象
NSURL *url = [NSURL URLWithString:self.urlString];


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


//开始链接获取数据
//先取消之前的链接
[self cancelDownLoader];


self.connection = [NSURLConnectionconnectionWithRequest:request
delegate:self];


}
}
}

#pragma mark - 获取路径的方法
- (NSString *)getPath
{

NSString *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,
YES).firstObject;


return path;


}

#pragma mark - 取消链接的方法
- (void)cancelDownLoader
{

[self.connectioncancel];

self.connection =nil;


}

- (void)dealloc
{


[_allDatarelease];

[_connection
release];

[_urlString
release];

_delegate =
nil;
[superdealloc];
}

@end

model类:

//

// ItemModel.h

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

@interface ItemModel :NSObject

@property (nonatomic ,retain)NSString *end_date;

@property (nonatomic ,retain)NSString *idd;

@property (nonatomic ,retain)NSString *photo;

@property (nonatomic ,retain)NSString *price;

@property (nonatomic ,retain)NSString *priceoff;

@property (nonatomic ,retain)NSString *title;

@property (nonatomic ,retain)UIImage *picImage;

//用字典给model赋值
+ (ItemModel *)itemModelWithDictionary:(NSDictionary *)infoDic;

//下载图片的方法
- (void)loadItemImage;

@end

//

// ItemModel.m

// KVODemo

//

// Created by lanouhn on 15-8-18.

// Copyright (c) 2015年
尹江涛-lesson16-8.18. All rights reserved.

//

#import "ItemModel.h"

#import "ImageDownLoader.h"

@interface
ItemModel ()<imageDownLoaderDelegate>

@end

@implementation ItemModel

#pragma mark - 初始化
- (instancetype)initWithDic:(NSDictionary *)infoDic
{


self = [superinit];
if (self) {

//给model赋值
for (NSString *keyin infoDic) {
if ([key
isEqualToString:@"end_date"]) {


self.end_date = infoDic[@"end_date"];


}else
if([keyisEqualToString:@"id"]) {


self.idd = infoDic[@"id"];
}else
if ([keyisEqualToString:@"price"]){
self.price = infoDic[@"price"];
}else
if ([keyisEqualToString:@"priceoff"]){
self.priceoff = infoDic[@"priceoff"];
}else
if ([keyisEqualToString:@"title"]){
self.title = infoDic[@"title"];
}else
if ([keyisEqualToString:@"photo"]){
//首先给属性赋值
self.photo = infoDic[@"photo"];
//得到imageName
//将字符串的/替换成_

NSString *imageName = [self.photostringByReplacingOccurrencesOfString:@"/"withString:@"_"];


//获得要缓存的路径
NSString *filePath = [[selfgetPath]
stringByAppendingPathComponent:imageName];


//创建文件夹管理对象
NSFileManager *fileManager = [NSFileManagerdefaultManager];



//判断路径下面有没有该缓存的文件
//路径是否存在
if ([fileManager
fileExistsAtPath:filePath]) {


//如果存在直接拿出用
self.picImage = [UIImageimageWithContentsOfFile:filePath];


}else {


//没有该缓存图片 去下载该图片
//model不管 谁用谁去下载


}
}
}
}

return
self;


}

#pragma mark - imageDownLoader代理方法
- (void)imageDownLoader:(ImageDownLoader *)imageDownLoader downLoadSuccessWithImage:(UIImage
*)image
{
self.picImage = image;
}

#pragma mark - 下载失败
- (void)imageDownLoader:(ImageDownLoader *)imageDownLoader failedWithError:(NSError
*)error
{

NSLog(@"%@",[errorlocalizedDescription]);


}

#pragma mark - 获得缓存路径的方法
- (NSString *)getPath
{

//获得应用程序文件路径

NSString *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,
YES ).firstObject;
return path;
}

#pragma mark - 用字典给model赋值
+ (ItemModel *)itemModelWithDictionary:(NSDictionary *)infoDic
{
ItemModel *model = [[ItemModelalloc]
initWithDic:infoDic];


return [model
autorelease];
}

#pragma mark - xiazai下载图片的方法
- (void)loadItemImage
{

//调用图片下载类去下载图片

[[ImageDownLoaderalloc]
initWithUrlString:self.photoandDelegate:self];


}
- (void)dealloc
{

[_end_date
release];
[_photorelease];
[_pricerelease];

[_priceoff
release];
[_titlerelease];
[_iddrelease];

[_picImage
release];
[superdealloc];
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: