用代理设计模式实现团购界面
2013-11-15 09:39
549 查看
1.Delegate的背景及使用场合
1.1背景:
分析 http://blog.csdn.net/sunnyboy9/article/details/16335301 里的实例 可知view离不开控制器, MJTgFooterView里面有 MJViewController *Controller这个属性 所以MJTgFooterView紧紧的依赖控制器,耦合性太强,假设控制器改变了,或者MJTgFooterView改变了,则整个系统都会挂掉,耦合性太强, 所以必须将其封装独立出来。1.2Delegate的使用场合
对象A内部发生了一些事情,想通知对象B对象B想监听对象A内部发生了什么事情
对象A想在自己的方法内部调用对象B的某个方法,并且对象A不能对对象B有耦合依赖
对象A想传递数据给对象B
2.使用delegate的步骤
先搞清楚谁是谁的代理(delegate)定义代理协议,协议名称的命名规范:控件类名 + Delegate
定义代理方法
代理方法一般都定义为@optional
代理方法名都以控件名开头
代理方法至少有1个参数,将控件本身传递出去
设置代理(delegate)对象 (比如myView.delegate = xxxx;)
代理对象遵守协议
代理对象实现协议里面该实现的方法
在恰当的时刻调用代理对象(delegate)的代理方法,通知代理发生了什么事情
(在调用之前判断代理是否实现了该代理方法)
……
以上情况,结果都一样:对象B是对象A的代理(delegate)
3.MVC
MVC是一种设计思想,贯穿于整个iOS开发中,需要积累一定的项目经验,才能深刻体会其中的含义和好处MVC中的三个角色
M:Model,模型数据
V:View,视图(界面)
C:Control,控制中心
MVC的几个明显的特征和体现:
View上面显示什么东西,取决于Model
只要Model数据改了,View的显示状态会跟着更改
Control负责初始化Model,并将Model传递给View去解析展示
4.用代理实现下面效果
5.具体实现
5.1搭建界面
5.1.1(MJTgFooterView.xib
5.1.2MJTgCell.xib
5.2plist文件
5.3 代码实现
5.3.1模型类
// // MJTg.h #import <Foundation/Foundation.h> @interface MJTg : NSObject /** * 标题 */ @property (nonatomic, copy) NSString *title; /** * 价格 */ @property (nonatomic, copy) NSString *price; /** * 图片 */ @property (nonatomic, copy) NSString *icon; /** * 购买人数 */ @property (nonatomic, copy) NSString *buyCount; + (instancetype)tgWithDict:(NSDictionary *)dict; - (instancetype)initWithDict:(NSDictionary *)dict; @end
// // MJTg.m #import "MJTg.h" @implementation MJTg + (instancetype)tgWithDict:(NSDictionary *)dict { return [[self alloc] initWithDict:dict]; } - (instancetype)initWithDict:(NSDictionary *)dict { if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self; } @end
5.3.2用MJTgCell类封装MJTgCell.xib
// // MJTgCell.h #import <UIKit/UIKit.h> @class MJTg; @interface MJTgCell : UITableViewCell /** * 通过一个tableView来创建一个cell */ + (instancetype)cellWithTableView:(UITableView *)tableView; /** * 团购模型 */ @property (nonatomic, strong) MJTg *tg; @end
// // MJTgCell.m #import "MJTgCell.h" #import "MJTg.h" @interface MJTgCell() @property (weak, nonatomic) IBOutlet UIImageView *iconView; @property (weak, nonatomic) IBOutlet UILabel *titleView; @property (weak, nonatomic) IBOutlet UILabel *priceView; @property (weak, nonatomic) IBOutlet UILabel *buyCountView; @end @implementation MJTgCell + (instancetype)cellWithTableView:(UITableView *)tableView { static NSString *ID = @"tg"; MJTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { // 从xib中加载cell cell = [[[NSBundle mainBundle] loadNibNamed:@"MJTgCell" owner:nil options:nil] lastObject]; } return cell; } - (void)setTg:(MJTg *)tg { _tg = tg; // 1.图片 self.iconView.image = [UIImage imageNamed:tg.icon]; // 2.标题 self.titleView.text = tg.title; // 3.价格 self.priceView.text = [NSString stringWithFormat:@"¥%@", tg.price]; // 4.购买数 self.buyCountView.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount]; } @end
5.3.3用MJTgFooterView类封装MJTgFooterView.xib
// // MJTgFooterView.h #import <UIKit/UIKit.h> @class MJTgFooterView; /** 1.协议名称: 控件类名 + Delegate 2.代理方法普遍都是@optional 3. */ @protocol MJTgFooterViewDelegate <NSObject> @optional - (void)tgFooterViewDidClickedLoadBtn:(MJTgFooterView *)tgFooterView; @end @interface MJTgFooterView : UIView /** * 快速创建一个footerView对象 */ + (instancetype)footerView; @property (nonatomic, weak) id<MJTgFooterViewDelegate> delegate; @end
// // MJTgFooterView.m #import "MJTgFooterView.h" @interface MJTgFooterView() - (IBAction)loadBtnClick; @property (weak, nonatomic) IBOutlet UIButton *loadBtn; @property (weak, nonatomic) IBOutlet UIView *loadingView; @end @implementation MJTgFooterView + (instancetype)footerView { return [[[NSBundle mainBundle] loadNibNamed:@"MJTgFooterView" owner:nil options:nil] lastObject]; } /** * 点击"加载"按钮 */ - (IBAction)loadBtnClick { // 1.隐藏加载按钮 self.loadBtn.hidden = YES; // 2.显示"正在加载" self.loadingView.hidden = NO; // 3.显示更多的数据 // GCD dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 3.0s后执行block里面的代码 // 通知代理 if ([self.delegate respondsToSelector:@selector(tgFooterViewDidClickedLoadBtn:)]) { [self.delegate tgFooterViewDidClickedLoadBtn:self]; } // 4.显示加载按钮 self.loadBtn.hidden = NO; // 5.隐藏"正在加载" self.loadingView.hidden = YES; }); } @end
5.4控制器
// // MJViewController.m #import "MJViewController.h" #import "MJTg.h" #import "MJTgCell.h" #import "MJTgFooterView.h" #import "MJTgHeaderView.h" @interface MJViewController () <UITableViewDataSource, MJTgFooterViewDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong) NSMutableArray *tgs; @end @implementation MJViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置每一行cell的高度 self.tableView.rowHeight = 80; // 设置footerView MJTgFooterView *footer = [MJTgFooterView footerView]; footer.delegate = self; self.tableView.tableFooterView = footer; // 设置headerView self.tableView.tableHeaderView = [MJTgHeaderView headerView]; // 设置tableView尾部显示的控件(tableFooterView的宽度永远是tableView的宽度) // tableFooterView只需要设置高度 // UIButton *footerBtn = [UIButton buttonWithType:UIButtonTypeSystem]; // footerBtn.frame = CGRectMake(0, 0, 0, 35); // footerBtn.backgroundColor = [UIColor orangeColor]; // [footerBtn setTitle:@"加载更多团购" forState:UIControlStateNormal]; // UINib *nib = [UINib nibWithNibName:@"MJTgFooterView" bundle:[NSBundle mainBundle]]; // 创建nib对象 // UINib *nib = [UINib nibWithNibName:@"MJTgFooterView" bundle:nil]; // // // 加载xib\nib // UIView *footerView = [[nib instantiateWithOwner:nil options:nil] lastObject]; // self.tableView.tableFooterView = footerView; } #pragma mark - MJTgFooterViewDelegate方法 /** * 加载更多的数据 */ - (void)tgFooterViewDidClickedLoadBtn:(MJTgFooterView *)tgFooterView { #warning 正常开发:发送网络请求给远程的服务器 // 1.添加更多的模型数据 MJTg *tg = [[MJTg alloc] init]; tg.icon = @"ad_01"; tg.title = @"新增加的团购数据.."; tg.price = @"100"; tg.buyCount = @"0"; [self.tgs addObject:tg]; // 2.刷新表格(告诉tableView重新加载模型数据, 调用tableView的reloadData) [self.tableView reloadData]; } /** * 隐藏状态栏 */ - (BOOL)prefersStatusBarHidden { return YES; } /** * 数据的懒加载 */ - (NSMutableArray *)tgs { if (_tgs == nil) { // 初始化 // 1.获得plist的全路径 NSString *path = [[NSBundle mainBundle] pathForResource:@"tgs.plist" ofType:nil]; // 2.加载数组 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path]; // 3.将dictArray里面的所有字典转成模型对象,放到新的数组中 NSMutableArray *tgArray = [NSMutableArray array]; for (NSDictionary *dict in dictArray) { // 3.1.创建模型对象 MJTg *tg = [MJTg tgWithDict:dict]; // 3.2.添加模型对象到数组中 [tgArray addObject:tg]; } // 4.赋值 _tgs = tgArray; } return _tgs; } #pragma mark - 数据源方法 /** * 一共有多少行数据 */ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.tgs.count; } /** * 每一行显示怎样的cell */ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell MJTgCell *cell = [MJTgCell cellWithTableView:tableView]; // 2.给cell传递模型数据 cell.tg = self.tgs[indexPath.row]; return cell; } @end
6.总结
这样使用代理设计模式完成上面的软件,则假设哪天控制器变化对view没有任何影响,从而实现了封装。相关文章推荐
- 代理设计模式——实现九宫格界面
- 设计模式之第16章-代理模式(Java实现)
- 设计模式---代理模式(c++实现)
- C#中利用代理实现观察者设计模式
- Android设计模式之动态代理,实现方法拦截功能
- 设计模式之动态代理(Java的JDK动态代理实现)
- 设计模式--JDK动态代理的实现与原理解析(1)
- 设计模式--JDK动态代理的实现与原理解析(2)
- 23种设计模式之python实现--代理(Proxy)模式
- Java设计模式之代理模式实现及原理
- Java设计模式菜鸟系列(十四)代理模式建模与实现
- Python实现设计模式--06.代理模式(Proxy Pattern)
- 设计模式--代理模式--Java实现
- 设计模式C++实现(8)——代理模式
- 设计模式C++实现(8)——代理模式
- 设计模式:用Java动态代理实现AOP
- Java开发-Java中代理设计模式的实现
- 设计模式之动态代理的代码实现(Java)
- 最常用的设计模式---代理模式(C++实现)
- 动态代理技术实现设计模式-代理模式