透过Delegate ,看UIView与UIViewController之间的关系 :
在Cocoa Touch 框架中, 所有的控件和视图都继承于UIView。 UIView 负责UI 的展示。UIView所接收到的触摸事件,都以Delegate的方式,交给UIViewController来处理。
需要注意的是,每个UIView都有自己的UIViewController。 比如,我们常用到的UITableView,它所对应的Controller就是UITableViewController。
接下来,我们看看UIView 的架构是怎样的。
简单回顾下@interface 和@protocol 这两个关键字。
@interface 用来定义一个类;
@protocol 用来定义一个协议; 也可以理解为,@protocol就是定义了一个protocol。 至于为什么叫 protocol, 不妨认为这是Objective-C 独有的东西吧。
第一步: 在 view.h 文件中声明一个delegate
(1) 定义一个UIView类
首先,定义一个UIView 的子类:
@interface MyUIView: UIView
{
@property id<MyUIViewDelegate> delegate;
}
@end
其他都容易理解,难点在于 delegate的定义和实现上。
先有个感性认识吧:出现<> 的地方,表示这是一个protocol类型。 Protocol前的id 是一个通用类型。暂且不管它。
id<MyUIViewDelegate> delegate; 这行代码表示, 我们用 <MyUIViewDelegate> 定义了一个protocol, 并且,把这个新定义的protocol 命名为delegate。
或许你感到纳闷,为什么非得命名为delegate 呢? 其实啊,这只是声明的一个protocol, 它与我们挂在嘴边的delegate 术语,没什么关系。
先提示下, delegate 是一种设计模式。 在Objective-C中, 它是通过protocol 的定义来实现的。
不过,按照Cocoa 的习惯, 在UIView 中所声明的这个protocol,一般都是命名为delegate,或以delegate 结尾。
(2) 声明一个protocol
通过@protocol,可以 定义一组函数。从本质上来说,这些函数就是回调函数。
@protocol MyUIViewDelegate
- method_a;
- method_b;
@end
MyUIViewDelegate 这种以 delegate结尾的命名方法, 预示着这个protocol将要完成delegate 所肩负的职责。
第二步: 在 viewController 文件中,实现这个delegate
设计自己的UIViewController 一个简单的做法是,让这个Controller来实现上面定义的MyUIViewDelegate。在Cocoa框架中,很多控件和它的Controller都是采用的这种方式。
{
//方法声明; (method declaration)
//属性声明(Property declaration)
}
@end
建立view、 delegate、 view controller 三者之间的关系
我们已经定义了 MyUIView、<MyUIViewDelegate> 和 MyUIViewController。
到这里其实还看不出这三者是怎么关联的。接下来就要看看,MyUIView和MyUIViewController的具体实现了。
首先是MyUIView的实现代码,假设在MyUIView视图中发生某个事件后,会调用doSometing方法。
- (void)doSomething
{
if( delegate != nil )
{
[delegate method_a];
}
}
if( delegate != nil ) 这行语句的意思是,如果delegate对象不为空,则调用相应的方法,但是这个对象的方法 (method_a)在哪里实现呢? 按照Delegate 的设计模式, MyUIViewDelegate所定义的方法,应由MyUIViewController 来实现。 代码如下:
在 viewcontroller. m 文件中, 实现以下代码:
- (id)init
{
MyUIView *myView = [[MyUIView alloc] init]; //对MyUIView进行初始化
myView.delegate = self; // 将MyUIViewController自己的实例作为委托对象
self.view = myView;
}
解释: 这里的self 所指的就是 viewcontroller。 myView.delegate = self; 的意思: 将view 的委托设为 view controller。 通俗地讲: 视图所委托的活儿,由视图控制器完成。
- (void)method_a
{
……
}
小结
这么一来,整个代码的思路,就很清晰了。
1. 重写 MyUIViewController初始化函数;
2. 初始化MyUIView,并将MyUIView的委托对象设为 MyUIViewController;
3. 当MyUIView有事件触发时,调用MyUIViewDelegate所定义的方法。