1.场景描述
在iOS开发过程中,一般都是UIViewController来控制UIView的行为,一般很少方向交互,即UIView的特性变化后调用UIViewController的相应的方法,在遇到这种情况,大多数都采用了在UIView的子类中放一个UIViewController的指针,当UIView需要调用UIViewController的方法的时候,就可以通过这个指针来实现了。
2.解决方案
这种方法是有效的(C/C++常用哦),但总是觉得不够优雅,有没有其他办法来实现呢,答案是肯定的,估计很多人都已经想到了,那就是委托(Delegate),其实iOS中很多界面元素都使用这种方式与UIViewController交互,这种方式给人的感觉更“Apple化"一些!
3.主要知识点
委托是Cocoa中最简单、最灵活的模式之一。委托是指给一个对象提供机会对另一个对象中的变化做出反应或者影响另一个对象的行为。其基本思想是:两个对象协同解决问题。一个对象非常普通,并且打算在广泛的情形中重用。它存储指向另一个对象(即它的委托)的引用,并在关键时刻给委托发消息。消息可能只是通知委托发生了某件事情,给委托提供机会执行额外的处理,或者消息可能要求委托提供一些关键的信息以控制所发生的事情。
委托模式能够起到两方面的作用:
第一:委托协助对象主体完成某项操作,将需要定制化的操作通过委托对象来自定义实现,达到和子类化对象主体同样的作用。
第二:事件监听,委托对象监听对象主体的某些重要事件,对事件做出具体响应或广播事件交给需要作出响应的对象。
个人理解采用委托模式的好处在于:
A、避免子类化带来的过多的子类以及子类与父类的耦合
B、通过委托传递消息机制实现分层解耦
4.请看代码
4.1实现委托前的代码
4.1.1 MainViewController.h
// // MainViewController.h // WellLogGraph // // Created by wanglei on 13-8-23. // Copyright (c) 2013年 wanglei. All rights reserved. // #import <UIKit/UIKit.h> @interface MainViewController : UIViewController @end
4.1.2 MainViewController.m
// // MainViewController.m // WellLogGraph // // Created by wanglei on 13-8-23. // Copyright (c) 2013年 wanglei. All rights reserved. // #import "MainViewController.h" #import "WellLogMapView.h" @interface MainViewController () @end @implementation MainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } -(void)viewWillAppear:(BOOL)animated { WellLogMapView* v = (WellLogMapView*)self.view; [v setNeedsDisplay]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
4.1.3 WellLogMapView.h
// // WellLogMapView.h // WellLogGraph // // Created by wanglei on 13-8-24. // Copyright (c) 2013年 wanglei. All rights reserved. // #import <UIKit/UIKit.h> @interface WellLogMapView : UIView { } @end
4.1.4 WellLogMapView.m
// // WellLogMapView.m // WellLogGraph // // Created by wanglei on 13-8-24. // Copyright (c) 2013年 wanglei. All rights reserved. // #import "WellLogMapView.h" @implementation WellLogMapView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { //UITouch *touch = [touches anyObject]; // 希望在这里告诉MainViewController做一些活动,也就是如何调用MainViewController的方法 } @end
4.2实现委托后的代码
4.2.1 MainViewController.h
// // MainViewController.h // WellLogGraph // // Created by wanglei on 13-8-23. // Copyright (c) 2013年 wanglei. All rights reserved. // #import <UIKit/UIKit.h> @protocol WellLogMapViewDelegate -(void)onSelectionChanged:(id)selection; @end @interface MainViewController : UIViewController<WellLogMapViewDelegate> -(void)onSelectionChanged:(id)selection; @end
4.2.2 MainViewController.m
// // MainViewController.m // WellLogGraph // // Created by wanglei on 13-8-23. // Copyright (c) 2013年 wanglei. All rights reserved. // #import "MainViewController.h" #import "WellLogMapView.h" @interface MainViewController () @end @implementation MainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.rightBarButtonItem.title = @"添加分栏"; [self.navigationItem.rightBarButtonItem initWithBarButtonSystemItem:UIBarButtonSystemItemUndo target:self action:@selector(myAction)]; WellLogMapView* view = (WellLogMapView*)self.view; [view setDelegate:self]; } -(void)viewWillAppear:(BOOL)animated { WellLogMapView* v = (WellLogMapView*)self.view; [v setNeedsDisplay]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)onSelectionChanged:(id)selection { //do something } @end
4.2.3 WellLogMapView.h
// // WellLogMapView.h // WellLogGraph // // Created by wanglei on 13-8-24. // Copyright (c) 2013年 wanglei. All rights reserved. // #import <UIKit/UIKit.h> #import "MainViewController.h" @interface WellLogMapView : UIView { id<WellLogMapViewDelegate> delegate; } @property (nonatomic, retain) id delegate; @end
4.2.4 WellLogMapView.m
// // WellLogMapView.m // WellLogGraph // // Created by wanglei on 13-8-24. // Copyright (c) 2013年 wanglei. All rights reserved. // #import "WellLogMapView.h" @implementation WellLogMapView @synthesize delegate; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { //UITouch *touch = [touches anyObject]; [delegate onSelectionChanged:nil]; } @end