• OC基础回想(十二)协议


    在OC基础(十一)中我们讨论了类别和非正式协议的奇异之处。在使用非正式协议时。能够仅仅实现你想要获得响应的方法。也不必在对象中声明不论什么内容来表示该对象可用作托付对象。

    全部这些任务能够用最少的代码完毕。

    以下来学习正式协议。

    1. 正式协议

         与非正式协议一样。正式协议包括了方法和属性的有名称列表。

    但与非正式协议不同的是,正式协议须要显示地採用。採用(adopt)协议的办法是在类的@interface声明中列出协议的名称。採用协议后,你的类就要遵守该协议。採用协议就意味着你承诺实现该协议的全部方法。否则,编译器会生成警告来提醒你。

    1.1 声明协议

    声明一个协议的方法很easy:
    @protocol myProtocol <NSObject>
     @required
    -(void)protocolMethodA:(NSString *)string;
    @optional
    -(void)protocolMethodB:(NSString *)string;
    @end

    说明:
    (1)第一行是声明这个协议的名字为myProtocol。尖括号里的NSObject本身也是一个协议,当中定义了非常多主要的协议函数。比方performSelector。isKindOfClass,respondsToSelector,conformsToProtocol,retain,release等。
    (2)协议接口分为required和optional两类。required顾名思义是说遵守这个协议的那个类“必需要”实现的接口,而optional则是能够实现也能够不实现的。协议接口的定义和普通的函数定义是一样的。

    (3)最后一行@end表示协议定义结束。这个协议的定义一般是在.h文件里。


    1.2 定义一个类遵循这个协议

    @interface myClass <myProtocol>
    @intrerface myClass : NSObject <myProtocol>
    @interface myClass : NSObject <myProtocol, NSCoding>
    说明:
    上面各自是三种不同的情况。编译的时候编译器会自己主动检查myClass是否实现了myProtocol中的必要的(@required)接口。假设没有实现则会发出一个警告信息。另外须要注意的是,假设有继承自myClass的子类,这些子类也是会自己主动遵循myClass所遵循的协议的。并且也能够重载这些接口。


    2.为什么要使用正式协议

    苹果的官方文档指出三个原因:

    • To declare methods that others are expected to implement
    • To declare the interface to an object while concealing its class
    • To capture similarities among classes that are not hierarchically related

    事实上还有第四个非常重要的原因,那就是降低继承类的复杂性。一个经典的样例就是iOS UI框架里面的UITableViewController类。假如没有“协议”功能。用户就必须选择用继承和重载接口的方法来实现复杂的UI控制以及其它事件的处理——这就对基类的设计提出了更大的挑战了。对于像这样一个table view,一个非常好的实现方法就是採用协议,由协议里的接口来控制不同的数据源以及各种复杂的用户操作。

    UIKit中设计了两个非常好的协议UITableViewDelegate,UITableViewDataSource来实现UITableViewController的控制。

    不论什么遵循这两个协议的类都能够实现对UITableView的控制。


    3.关于id类型的运用

         id 类型在iOS中是一个通用类型,有点类似C语言的void*类型。编译器不能检查到定义为id类型的变量的实际类型,id类型的识别是发生在执行时阶段。可是我们能够用 id<protocol_name> obj;这种语法形式在编译阶段就能够让编译器知道obj仅仅能够发送protocol_name中的消息,假设所发送的消息不在protocol_name中,编译器会给一个警告信息“Instance method 'xxxx:' not found......”。

    这样的情况多用于代理模式的实现。比方某一个类有一个delegate 的property:

    id <myProtocol> delegate;
         这样。在编译阶段我们就能够知道用delegate所发送的消息是不是在它所遵循的myProtocol中的消息。好了。 到这里笔者钻起了牛角尖,我把id后面的 <myProtocol>删掉。然后用delegate发送一个并不存在于myProtocol中的消息。结果编译器还是给了“Instance method 'xxxx:' not found......”的警告信息。

    更奇怪的是,当发送一个存在于myProtocol中的消息时,编译器居然没有这种警告信息。这两个測试并不能说明之前的解释是错误的,姑且觉得id<myProtocol> delegate这种写法是为了便于知道这个delegate遵循了myProtocol的协议吧

  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7119905.html
Copyright © 2020-2023  润新知