UI-KVO设计模式Demo

3 篇文章 0 订阅
2 篇文章 0 订阅

在这个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 = [[UITableViewCellallocinitWithStyle: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"];

        

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

        [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"];

    

    //拿到当前界面所有显示的cellindexPath

   NSArray *indexPathsArray = [self.tableViewindexPathsForVisibleRows];

    

    //判断要更新的cellindexpath是否在显示列表里面

   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




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值