iOS编程之协议(procotol)

需要了解ios协议, 首先看一个代码示例:

  • 流氓协议(YHBadManDelegate.h)
    #import <Foundation/Foundation.h>
    /**流氓协议*/
    @protocol BadManDelegate <NSObject>
    @required // 必须实现的方法
    /**吃*/
    - (void) eat;
    /**骗*/
    - (void) lie;
    @optional // 可选实现的方法
    - (void) drink;
    @end
  • 君子协议(GentlemanDelegate.h)
    /**君子协议*/
    @protocol GentlemanDelegate <NSObject>
    // 协议内容只能有方法不能有属性
    // 协议方法
    /**动口不动手*/
    - (void) fight;
    /**爱钱取之有道*/
    - (void) loveMoney;
    @end
  • 初始化遵守协议的对象
    #import <Foundation/Foundation.h>
    #import "BadManDelegate.h"
    #import "GentlemanDelegate.h"

    // 遵守协议的类就是代理类; 如果一个类遵守了协议, 就要去实现协议方法;
    /**遵守流氓协议的代理*/
    // 一个类可以同时遵守多个协议, 在一个<>中多个协议名用逗号隔开
    @interface YHPerson : NSObject <BadManDelegate, GentlemanDelegate>

    @end

    @interface YHStudent : NSObject <BadManDelegate>

    - (void) study;

    @end
  • 实现协议
    #import "YHPerson.h"

    @implementation YHPerson
    - (void) eat {
        NSLog(@"正在吃霸王餐!!");
    }
    - (void) lie {
        NSLog(@"在撒谎!!");
    }
    - (void) fight {
        NSLog(@"动口不动手!!");
    }
    - (void) loveMoney {
        NSLog(@"爱钱取之有道!!");
    }
    @end
    @implementation YHStudent
    // 实现学生相关的方法
    - (void) study {
        NSLog(@"Good Good Study, Day Day Up.");
    }
    // 实现流氓协议的方法
    - (void) eat {
        NSLog(@"吃完带抢");
    }
    - (void) lie {
        NSLog(@"处处留情!!");
    }
    @end

这里说明几点:

  1. 一个协议可以扩展自另一个协议,例如上面BadManDelegate就扩展自NSObject,如果需要扩展多个协议中间使用逗号分隔;
  2. 和其他高级语言中接口不同的是协议中定义的方法不一定是必须实现的,我们可以通过关键字进行@required和@optional进行设置,如果不设置则默认是@required(注意ObjC是弱语法,即使不实现必选方法编译运行也不会报错);
  3. 协议通过<>进行实现,一个类可以同时实现多个协议,中间通过逗号分隔;
  4. 协议的实现只能在类的声明上,不能放到类的实现上(也就是说必须写成@interface YHPerson:NSObject <AnimalDelegate>而不能写成@implementation YHPerson<AnimalDelegate>);
  5. 协议中不能定义属性、成员变量等,只能定义方法;

由上例可以看出,iOS中的协议其实和生活中的协议基本上是一样的,比如生活中签订的就业协议、保密协议以及一些合同等等。而协议本身就是一系列的条款及规定(在OC中的协议主要看的是甲方对乙方指定的规定)。

  • 协议的基本概念

    • 委托: 即签订协议时的甲方(指定协议)
    • 代理: 即签订协议时的乙方(遵守协议)
    • 协议: 甲方对乙方的规定、要求(OC中的实质就是一系列的方法)
  • 协议的特点

    • 一个类可以同时遵守多个协议(遵守协议后必须实现协议方法)
    • 同一个协议可以被多个类遵守, 不同的类中协议方法可以有不同的实现
  • 协议的主要要求
    遵守协议就是要做到协议上规定的内容, 遵守什么样的协议就需要做什么样的对象

    例如:
    1、君子协议
    协议内容: 君子动口不动手、君子爱财取之有道、君子爱美取只有礼等
    君子: 遵守君子协议的人
    2、流氓协议
    协议内容: 吃喝嫖赌、坑蒙拐骗偷等
    流氓: 遵守流氓协议的人

  • 使用协议代理解决问题需要找到三要素(协议、代理、委托)
    • 委托: 老板 (想要做某件事情, 但是自己没有能力去做, 需要别人来帮他完成)
    • 协议: 会iOS开发 (委托对代理的要求, 委托想要代理帮他做的事情)
    • 代理: 遵守协议的对象 (实际做事情的对象)

使用协议代理解决问题: (如果一个对象想要做一件事情(完成一个功能), 但是自己做不到, 需要一个可以做到的对象来帮他完成, 考虑使用协议代理)
  场景: 老板想要做一个iOS项目
  分析: 老板想做iOS项目, 但是自己不会做, 找一个会iOS开发的人来帮他做

  • YHBoss.h
    #import <Foundation/Foundation.h>
    //2.协议
    /**声明协议*/
    @protocol StaffDelegate <NSObject>
    /**会IOS开发(做开发)*/
    - (void) codeIOS;
    @end
    // 1. 委托
    // 委托需要一个遵守协议的对象来帮他做事情 (委托需要一个代理)
    /**委托类(制定协议)*/
    @interface YHBoss : NSObject
    // 任何遵守协议的类创建的对象都可以作为老板的代理
    // 注意: delegate要用weak修饰(防止循环引用造成对象不能销毁)
    /**代理*/
    @property (nonatomic, weak) id <StaffDelegate> delegate;
    // 告诉代理何时去做事情
    /**告诉代理*/
    - (void) askStaffWorking;
    @end
  • YHBoss.m
    #import "YHBoss.h"

    @implementation YHBoss
    //委托告诉代理做事
    - (void) askStaffWorking {
        NSLog(@"老板告诉员工开工");
        // 代理开始做事情
        [self.delegate codeIOS];
    }
    @end
  • YHPerson.h
    #import <Foundation/Foundation.h>
    #import "YHBoss.h"

    // 3.代理(遵守协议, 实现协议方法)
    /**代理*/
    @interface YHPerson : NSObject <StaffDelegate>
    @end
  • YHPerson.m
    #import "YHPerson.h"
    #import "YHBoss.h"

    @implementation YHPerson
    // 判断一个对象是否实现了某个方法
    // (这里判断self.delegate是否实现了buyPhone方法)
    if ([self.delegate respondsToSelector:@selector(codeIOS)]) {
        // 代理开始做事情
        [self.delegate codeIOS];
    }
    @end
  • main.h
    #import <Foundation/Foundation.h>
    #import "YHPerson.h"

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 1.首先需要一个boss
            YHBoss *boss = [[YHBoss alloc] init];
            // 2.需要一个员工
            YHPerson *person = [[YHPerson alloc] init];
            // 3.让员工成为老板的代理
            boss.delegate = person;
            // 4.老板喊开工
            [boss askStaffWorking];
        }
        return 0;
    }
  1. id可以表示任何一个ObjC对象类型,类型后面的”<协议名>“用于约束作为这个属性的对象必须实现该协议(注意:使用id定义的对象类型不需要加“*”);
  2. YHPerson作为事件触发者,它实现了YHBoss代理(在ObjC中没有命名空间和包的概念,通常通过前缀进行类的划分,“YH”是我们自定义的前缀);
  3. 在.h文件中如果使用了另一个文件的类或协议我们可以通过@class或者@protocol进行声明,而不必导入这个文件,这样可以提高编译效率(注意有些情况必须使用@class或@protocol),但是在.m文件中则必须导入对应的类声明文件或协议文件(如果不导入虽然语法检查可以通过但是编译链接会报错);
  4. 使用respondsToSelector方法可以判断一个对象是否实现了某个方法(如果方法后面需要参数,需要注意方法名不是”codeIOS”而是“codeIOS:”,冒号也是方法名的一部分);
  • 在实际开发过程中, 协议代理的作用:
    • 传值(反向传值)
    • 回调

反向传值###

  • 使用协议代理完成传值: 协议带参数(委托将要传得值, 通过协议方法的参数传给代理)
    场景: 上一级界面显示下一级界面的内容
    分析: 下一级界面想要将自己的内容显示在上一级界面, 但是自己做不到, 需要上一级界面来帮他完成
  • YHGreenInterface.h
    #import <Foundation/Foundation.h>

    @protocol GreenInterfaceDelegate <NSObject>
    // 让协议方法带参传值
    /**传递的值*/
    - (void) showAppointValue:(NSString *) value;
    @end
    /**绿色界面*/
    @interface YHGreenView : NSObject
    /**需要的代理*/
    @property (nonatomic, weak) id <GreenInterfaceDelegate> delegate;
    /**传递需要显示的数据*/
    - (void) deliverValue:(NSString *) value;
    @end
  • YHGreenInterface.m
    #import "YHGreenView.h"

    @implementation YHGreenView
    - (void) deliverValue:(NSString *) value {
        if ([self.delegate respondsToSelector:@selector(showAppointValue:)]) {
            [self.delegate showAppointValue:value];
        }
        else {
            NSLog(@"无法传值");
        }
    }
    @end
  • YHYellowInterface.h
    #import <Foundation/Foundation.h>
    #import "YHGreenView.h"

    // 遵守协议, 实现协议方法
    /**黄色界面*/
    @interface YHYellowView : NSObject <GreenInterfaceDelegate>
    @end
  • YHYellowInterface.m
    #import "YHYellowView.h"

    @implementation YHYellowView
    // 实现协议方法, 打印指定内容
    - (void) showAppointValue:(NSString *) value {
        printf("显示: %s", [value UTF8String]);
    }
    @end
  • main.h
    #import <Foundation/Foundation.h>
    #import "YHYellowView.h"

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 绿色界面委托
            YHGreenView *GreenView = [[YHGreenView alloc] init];
            // 黄色界面代理
            YHYellowView *YellowView = [[YHYellowView alloc] init];
            //将黄色界面设置为绿色界面的代理
            GreenView.delegate = YellowView;
            // 显示输入的内容
            printf("输入要显示的值:");
            char a[100];
            fgets(a, 101, stdin);
            // 传值
            [GreenView deliverValue:[NSString stringWithUTF8String:]];
        }
        return 0;
    }

回调###

- 协议代理回调作用: 通过协议方法的返回值, 将数据从代理传给委托
场景: 显示类想要得到从网上下载的数据
分析: 显示类不能去下载数据(不是因为没能力, 而是不想去做), 需要一个下载类去下载数据, 然后把数据给显示类
三要素
委托: 显示类(想要下载数据)
协议: 下载数据
代理: 下载类
  • YHShow.h
    #import <Foundation/Foundation.h>

    @protocol downloadDelegate <NSObject>
    /**下载指定路径下的数据*/
    - (NSData *) downloadDataWithURL:(NSString *) urlStr;
    @end
    // 1. 委托
    /**委托*/
    @interface YHShow : NSObject
    /**代理对象*/
    @property (nonatomic, weak) id <downloadDelegate> delegate;
    /**要求代理下载数据*/
    - (void) needShow;
    @end
  • YHShow.m
    #import "YHShow.h"

    @implementation YHShow
    - (void) needShow {
        if ([self.delegate respondsToSelector:@selector(downloadDataWithURL:)]) {
            NSData *data = [self.delegate downloadDataWithURL:@"http://blog.csdn.net/jingling/article/details/47753189"];
            NSLog(@"显示下载的数据%@", data);
        }
    }
    @end
  • YHDownload.h
    #import <Foundation/Foundation.h>
    #import "YHShow.h"

    /**代理*/
    @interface YHDownload : NSObject <downloadDelegate>
    @end
  • YHDownload.m
    #import "YHDownload.h"

    @implementation YHDownload
    - (NSData *) downloadDataWithURL:(NSString *) urlStr {
        // 获取指定网络路径中的数据
        // 创建统一资源定位符对象
        NSURL *url = [NSURL URLWithString:urlStr];
        NSData *data = [NSData dataWithContentsOfURL:url];
        return data;
    }
    @end
  • main.h
    #import <Foundation/Foundation.h>
    #import "YHDownload.h"

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 1.创建一个显示对象
            YHShow *show = [[YHShow alloc] init];
            // 2.创建一个下载对象
            YHDownload *download = [[YHDownload alloc] init];
            // 3.设置代理
            show.delegate = download;
            // 4.开始下载
            [show needShow];
        }
        return 0;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,134评论 30 470
  • 1.OC里用到集合类是什么? 基本类型为:NSArray,NSSet以及NSDictionary 可变类型为:NS...
    轻皱眉头浅忧思阅读 1,368评论 0 3
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,690评论 0 9
  • 1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch...
    阳光的大男孩儿阅读 4,971评论 0 13
  • 失去的语言 天凉好个秋啊 诗人说 ...
    忍冬寒阅读 582评论 8 6