protocol - 1
来源:互联网 发布:php-fpm 1000并发量 编辑:程序博客网 时间:2024/05/16 17:40
优秀的文章:http://www.cnblogs.com/kenshincui/p/3869639.html#protocol
http://www.cnblogs.com/wendingding/p/3709604.html
学习iOS的协议我们先来看看面相对象的接口是什么?以java为例:
接口
接口是另一种定义数据类型的方式。它和类非常相似的。
相同之处:都有成员变量和成员方法
也可以形成继承关系
不同之处:接口中的属性都是常量(final)
接口中的方法是抽象方法(没有方法体)
引入接口的原因:Java只支持单重继承,每个类只能有一个超类。但实际应用中有时候需要多重继承--使用接口,一个类可以实现多个接口。
看到这里就大概明白了Objective-C实现协议的重要性了吧,Objective-C是不支持多重继承的,所以可以使用protocol来完成多重继承的效果,细细一想就会明白,一个ViewController只会继承UIViewController类从而拥有相关的控制视图的能力,然而如果你想要在它的属性UIView上展示多样的效果,例如你可以实现<UITableViewDelegate>协议来实现,如果你想要特定操作有弹出狂的警示效果, 你可以实现<UIAlertViewDelegate>的协议等等。从而完成行为的多态性。
我们来看看最常用的协议UITableView的官方定义:
DataSource部分:
@protocol UITableViewDataSource<NSObject>@required- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;@optional- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;@end
@protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>@optional- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;@end
@property (nonatomic, assign) id <UITableViewDataSource> dataSource;@property (nonatomic, assign) id <UITableViewDelegate> delegate;
而在UITableView类的属性我们可以看到定义了两个id类型的变量,这个用 < SomeReusableDelegate > 约束起来的语法意义就是遵守这个协议。很显然不是所有的变量都命名为delegate,所以这一块语法叫ObjC的协议而不是委托,而委托delegate其实是一种设计模式,通过委托对象来实现所需的操作,而这种设计模式就是靠ObjC的协议来实现。
转大牛的一段话:
事实上在ObjC中协议的更多作用是用于约束一个类必须实现某些方法,而从面向对象的角度而言这个类跟接口并不一定存在某种自然关系,可能是两个完全不同意义上的事物,这种模式我们称之为代理模式(Delegation)。在Cocoa框架中大量采用这种模式实现数据和UI的分离,而且基本上所有的协议都是以Delegate结尾。
细细一想的确如此,实现两个协议protocol , 一个是dataSource 另外一个是delegate, 一个负责数据相关的方法的实现,另外一个负责UI相关的方法的实现,而这两者都是体现了约束的意味,你遵守了协议,你就必须去实现它们的方法,不然你遵守来干嘛?
而观察到每一个协议都会扩展<NSOject> (在创建的时候默认添加的),进入头文件一看:
@protocol NSObject- (BOOL)isEqual:(id)object;@property (readonly) NSUInteger hash;@property (readonly) Class superclass;- (Class)class;- (instancetype)self;- (id)performSelector:(SEL)aSelector;- (id)performSelector:(SEL)aSelector withObject:(id)object;- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;- (BOOL)isProxy;- (BOOL)isKindOfClass:(Class)aClass;- (BOOL)isMemberOfClass:(Class)aClass;- (BOOL)conformsToProtocol:(Protocol *)aProtocol;- (BOOL)respondsToSelector:(SEL)aSelector;- (instancetype)retain OBJC_ARC_UNAVAILABLE;- (oneway void)release OBJC_ARC_UNAVAILABLE;- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;@property (readonly, copy) NSString *description;@optional@property (readonly, copy) NSString *debugDescription;@end
这里协议和普通的类一样具备普遍的面向对象继承的特性,NSObject充当一个“根协议”的作用,这里面提供了很多很有用的方法,例如判断是否拥有响应方法等。根据这个面向对象的继承特性,父类如果遵守了一个协议,子类也会相应地遵守。但是这里最有趣的是这两个属性:
@property (readonly) NSUInteger hash;@property (readonly) Class superclass;
一个整形的hash哈希变量和一个超类的属性,什么鬼? 不是说协议是定义一组 “行为” (方法)规范的接口吗?为什么有属性变量的?即使java中的接口是能定义变量的(只能定义常量final变量),为此百度和google了一下:
http://bbs.csdn.net/topics/391027845
http://stackoverflow.com/questions/21023822/how-to-declare-variables-in-protocol
不纠结了,大体说的就是没有意义的定义方式,如果实在要用则具体情况而言来添加static和extern。
具体实现:
在视图控制器中,将这两项委托的代理人置给自身:
tableview.delegate = self; tableview.dataSource = self;
当然前提是要实现这个协议,不然会报下面这样的错误的哦:
另外提一个问题:为什么参数类型要填上weak ? 嘻嘻,其实就是防止(父子对象)之间循环引用导致的内存泄漏。
非常好的文章:http://bbs.9ria.com/thread-258284-1-1.html
- protocol - 1
- rtsp protocol (1)
- Protocol buffer(1)
- Protocol Buffers: (1) Overview
- Protocol Buffers 详解1
- Protocol
- protocol
- Protocol
- protocol
- @protocol
- Protocol
- Protocol
- protocol
- protocol
- protocol
- Protocol
- protocol
- protocol
- dbus1.0.2、libxm2交叉编译、安装
- Maven插件开发
- filter的配置和filter模板
- kafka测试时异常
- Use '$' instead of '.' for inner classes (or use only lowercase letters in package names) 问题
- protocol - 1
- poj1276 多重背包问题 转换为经典的01背包
- java获取文件创建时间
- [iOS]常用正则表达式
- 南邮 OJ 1576 斐波那契递推
- swift 一疑问:reduce
- 二代身份证号码校验方法
- [js动态报表][兼容IE6+/火狐/360/谷歌/等各大浏览器][可手动设置间隔时间读取数据/并且显示在图表上]
- Fragment的显示与隐藏及demo