iOS編程之協(xié)議(procotol)

需要了解ios協(xié)議, 首先看一個(gè)代碼示例:

  • 流氓協(xié)議(YHBadManDelegate.h)
    #import <Foundation/Foundation.h>
    /**流氓協(xié)議*/
    @protocol BadManDelegate <NSObject>
    @required // 必須實(shí)現(xiàn)的方法
    /**吃*/
    - (void) eat;
    /**騙*/
    - (void) lie;
    @optional // 可選實(shí)現(xiàn)的方法
    - (void) drink;
    @end
  • 君子協(xié)議(GentlemanDelegate.h)
    /**君子協(xié)議*/
    @protocol GentlemanDelegate <NSObject>
    // 協(xié)議內(nèi)容只能有方法不能有屬性
    // 協(xié)議方法
    /**動(dòng)口不動(dòng)手*/
    - (void) fight;
    /**愛錢取之有道*/
    - (void) loveMoney;
    @end
  • 初始化遵守協(xié)議的對(duì)象
    #import <Foundation/Foundation.h>
    #import "BadManDelegate.h"
    #import "GentlemanDelegate.h"

    // 遵守協(xié)議的類就是代理類; 如果一個(gè)類遵守了協(xié)議, 就要去實(shí)現(xiàn)協(xié)議方法;
    /**遵守流氓協(xié)議的代理*/
    // 一個(gè)類可以同時(shí)遵守多個(gè)協(xié)議, 在一個(gè)<>中多個(gè)協(xié)議名用逗號(hào)隔開
    @interface YHPerson : NSObject <BadManDelegate, GentlemanDelegate>

    @end

    @interface YHStudent : NSObject <BadManDelegate>

    - (void) study;

    @end
  • 實(shí)現(xiàn)協(xié)議
    #import "YHPerson.h"

    @implementation YHPerson
    - (void) eat {
        NSLog(@"正在吃霸王餐!!");
    }
    - (void) lie {
        NSLog(@"在撒謊!!");
    }
    - (void) fight {
        NSLog(@"動(dòng)口不動(dòng)手!!");
    }
    - (void) loveMoney {
        NSLog(@"愛錢取之有道!!");
    }
    @end
    @implementation YHStudent
    // 實(shí)現(xiàn)學(xué)生相關(guān)的方法
    - (void) study {
        NSLog(@"Good Good Study, Day Day Up.");
    }
    // 實(shí)現(xiàn)流氓協(xié)議的方法
    - (void) eat {
        NSLog(@"吃完帶搶");
    }
    - (void) lie {
        NSLog(@"處處留情!!");
    }
    @end

這里說明幾點(diǎn):

  1. 一個(gè)協(xié)議可以擴(kuò)展自另一個(gè)協(xié)議,例如上面BadManDelegate就擴(kuò)展自NSObject,如果需要擴(kuò)展多個(gè)協(xié)議中間使用逗號(hào)分隔;
  2. 和其他高級(jí)語言中接口不同的是協(xié)議中定義的方法不一定是必須實(shí)現(xiàn)的,我們可以通過關(guān)鍵字進(jìn)行@required和@optional進(jìn)行設(shè)置,如果不設(shè)置則默認(rèn)是@required(注意ObjC是弱語法,即使不實(shí)現(xiàn)必選方法編譯運(yùn)行也不會(huì)報(bào)錯(cuò));
  3. 協(xié)議通過<>進(jìn)行實(shí)現(xiàn),一個(gè)類可以同時(shí)實(shí)現(xiàn)多個(gè)協(xié)議,中間通過逗號(hào)分隔;
  4. 協(xié)議的實(shí)現(xiàn)只能在類的聲明上,不能放到類的實(shí)現(xiàn)上(也就是說必須寫成@interface YHPerson:NSObject <AnimalDelegate>而不能寫成@implementation YHPerson<AnimalDelegate>);
  5. 協(xié)議中不能定義屬性、成員變量等,只能定義方法;

由上例可以看出,iOS中的協(xié)議其實(shí)和生活中的協(xié)議基本上是一樣的,比如生活中簽訂的就業(yè)協(xié)議、保密協(xié)議以及一些合同等等。而協(xié)議本身就是一系列的條款及規(guī)定(在OC中的協(xié)議主要看的是甲方對(duì)乙方指定的規(guī)定)。

  • 協(xié)議的基本概念

    • 委托: 即簽訂協(xié)議時(shí)的甲方(指定協(xié)議)
    • 代理: 即簽訂協(xié)議時(shí)的乙方(遵守協(xié)議)
    • 協(xié)議: 甲方對(duì)乙方的規(guī)定、要求(OC中的實(shí)質(zhì)就是一系列的方法)
  • 協(xié)議的特點(diǎn)

    • 一個(gè)類可以同時(shí)遵守多個(gè)協(xié)議(遵守協(xié)議后必須實(shí)現(xiàn)協(xié)議方法)
    • 同一個(gè)協(xié)議可以被多個(gè)類遵守, 不同的類中協(xié)議方法可以有不同的實(shí)現(xiàn)
  • 協(xié)議的主要要求
    遵守協(xié)議就是要做到協(xié)議上規(guī)定的內(nèi)容, 遵守什么樣的協(xié)議就需要做什么樣的對(duì)象

    例如:
    1、君子協(xié)議
    協(xié)議內(nèi)容: 君子動(dòng)口不動(dòng)手、君子愛財(cái)取之有道、君子愛美取只有禮等
    君子: 遵守君子協(xié)議的人
    2、流氓協(xié)議
    協(xié)議內(nèi)容: 吃喝嫖賭、坑蒙拐騙偷等
    流氓: 遵守流氓協(xié)議的人

  • 使用協(xié)議代理解決問題需要找到三要素(協(xié)議、代理、委托)
    • 委托: 老板 (想要做某件事情, 但是自己沒有能力去做, 需要?jiǎng)e人來幫他完成)
    • 協(xié)議: 會(huì)iOS開發(fā) (委托對(duì)代理的要求, 委托想要代理幫他做的事情)
    • 代理: 遵守協(xié)議的對(duì)象 (實(shí)際做事情的對(duì)象)

使用協(xié)議代理解決問題: (如果一個(gè)對(duì)象想要做一件事情(完成一個(gè)功能), 但是自己做不到, 需要一個(gè)可以做到的對(duì)象來幫他完成, 考慮使用協(xié)議代理)
??場(chǎng)景: 老板想要做一個(gè)iOS項(xiàng)目
??分析: 老板想做iOS項(xiàng)目, 但是自己不會(huì)做, 找一個(gè)會(huì)iOS開發(fā)的人來幫他做

  • YHBoss.h
    #import <Foundation/Foundation.h>
    //2.協(xié)議
    /**聲明協(xié)議*/
    @protocol StaffDelegate <NSObject>
    /**會(huì)IOS開發(fā)(做開發(fā))*/
    - (void) codeIOS;
    @end
    // 1. 委托
    // 委托需要一個(gè)遵守協(xié)議的對(duì)象來幫他做事情 (委托需要一個(gè)代理)
    /**委托類(制定協(xié)議)*/
    @interface YHBoss : NSObject
    // 任何遵守協(xié)議的類創(chuàng)建的對(duì)象都可以作為老板的代理
    // 注意: delegate要用weak修飾(防止循環(huán)引用造成對(duì)象不能銷毀)
    /**代理*/
    @property (nonatomic, weak) id <StaffDelegate> delegate;
    // 告訴代理何時(shí)去做事情
    /**告訴代理*/
    - (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.代理(遵守協(xié)議, 實(shí)現(xiàn)協(xié)議方法)
    /**代理*/
    @interface YHPerson : NSObject <StaffDelegate>
    @end
  • YHPerson.m
    #import "YHPerson.h"
    #import "YHBoss.h"

    @implementation YHPerson
    // 判斷一個(gè)對(duì)象是否實(shí)現(xiàn)了某個(gè)方法
    // (這里判斷self.delegate是否實(shí)現(xiàn)了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.首先需要一個(gè)boss
            YHBoss *boss = [[YHBoss alloc] init];
            // 2.需要一個(gè)員工
            YHPerson *person = [[YHPerson alloc] init];
            // 3.讓員工成為老板的代理
            boss.delegate = person;
            // 4.老板喊開工
            [boss askStaffWorking];
        }
        return 0;
    }
  1. id可以表示任何一個(gè)ObjC對(duì)象類型,類型后面的”<協(xié)議名>“用于約束作為這個(gè)屬性的對(duì)象必須實(shí)現(xiàn)該協(xié)議(注意:使用id定義的對(duì)象類型不需要加“*”);
  2. YHPerson作為事件觸發(fā)者,它實(shí)現(xiàn)了YHBoss代理(在ObjC中沒有命名空間和包的概念,通常通過前綴進(jìn)行類的劃分,“YH”是我們自定義的前綴);
  3. 在.h文件中如果使用了另一個(gè)文件的類或協(xié)議我們可以通過@class或者@protocol進(jìn)行聲明,而不必導(dǎo)入這個(gè)文件,這樣可以提高編譯效率(注意有些情況必須使用@class或@protocol),但是在.m文件中則必須導(dǎo)入對(duì)應(yīng)的類聲明文件或協(xié)議文件(如果不導(dǎo)入雖然語法檢查可以通過但是編譯鏈接會(huì)報(bào)錯(cuò));
  4. 使用respondsToSelector方法可以判斷一個(gè)對(duì)象是否實(shí)現(xiàn)了某個(gè)方法(如果方法后面需要參數(shù),需要注意方法名不是”codeIOS”而是“codeIOS:”,冒號(hào)也是方法名的一部分);
  • 在實(shí)際開發(fā)過程中, 協(xié)議代理的作用:
    • 傳值(反向傳值)
    • 回調(diào)

反向傳值###

  • 使用協(xié)議代理完成傳值: 協(xié)議帶參數(shù)(委托將要傳得值, 通過協(xié)議方法的參數(shù)傳給代理)
    場(chǎng)景: 上一級(jí)界面顯示下一級(jí)界面的內(nèi)容
    分析: 下一級(jí)界面想要將自己的內(nèi)容顯示在上一級(jí)界面, 但是自己做不到, 需要上一級(jí)界面來幫他完成
  • YHGreenInterface.h
    #import <Foundation/Foundation.h>

    @protocol GreenInterfaceDelegate <NSObject>
    // 讓協(xié)議方法帶參傳值
    /**傳遞的值*/
    - (void) showAppointValue:(NSString *) value;
    @end
    /**綠色界面*/
    @interface YHGreenView : NSObject
    /**需要的代理*/
    @property (nonatomic, weak) id <GreenInterfaceDelegate> delegate;
    /**傳遞需要顯示的數(shù)據(jù)*/
    - (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"

    // 遵守協(xié)議, 實(shí)現(xiàn)協(xié)議方法
    /**黃色界面*/
    @interface YHYellowView : NSObject <GreenInterfaceDelegate>
    @end
  • YHYellowInterface.m
    #import "YHYellowView.h"

    @implementation YHYellowView
    // 實(shí)現(xiàn)協(xié)議方法, 打印指定內(nèi)容
    - (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];
            //將黃色界面設(shè)置為綠色界面的代理
            GreenView.delegate = YellowView;
            // 顯示輸入的內(nèi)容
            printf("輸入要顯示的值:");
            char a[100];
            fgets(a, 101, stdin);
            // 傳值
            [GreenView deliverValue:[NSString stringWithUTF8String:]];
        }
        return 0;
    }

回調(diào)###

- 協(xié)議代理回調(diào)作用: 通過協(xié)議方法的返回值, 將數(shù)據(jù)從代理傳給委托
場(chǎng)景: 顯示類想要得到從網(wǎng)上下載的數(shù)據(jù)
分析: 顯示類不能去下載數(shù)據(jù)(不是因?yàn)闆]能力, 而是不想去做), 需要一個(gè)下載類去下載數(shù)據(jù), 然后把數(shù)據(jù)給顯示類
三要素
委托: 顯示類(想要下載數(shù)據(jù))
協(xié)議: 下載數(shù)據(jù)
代理: 下載類
  • YHShow.h
    #import <Foundation/Foundation.h>

    @protocol downloadDelegate <NSObject>
    /**下載指定路徑下的數(shù)據(jù)*/
    - (NSData *) downloadDataWithURL:(NSString *) urlStr;
    @end
    // 1. 委托
    /**委托*/
    @interface YHShow : NSObject
    /**代理對(duì)象*/
    @property (nonatomic, weak) id <downloadDelegate> delegate;
    /**要求代理下載數(shù)據(jù)*/
    - (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(@"顯示下載的數(shù)據(jù)%@", 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 {
        // 獲取指定網(wǎng)絡(luò)路徑中的數(shù)據(jù)
        // 創(chuàng)建統(tǒng)一資源定位符對(duì)象
        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.創(chuàng)建一個(gè)顯示對(duì)象
            YHShow *show = [[YHShow alloc] init];
            // 2.創(chuàng)建一個(gè)下載對(duì)象
            YHDownload *download = [[YHDownload alloc] init];
            // 3.設(shè)置代理
            show.delegate = download;
            // 4.開始下載
            [show needShow];
        }
        return 0;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,125評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,402評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,934評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,168評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,690評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,596評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,027評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,398評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,743評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,182評(píng)論 30 470
  • 1.OC里用到集合類是什么? 基本類型為:NSArray,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,390評(píng)論 0 3
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,745評(píng)論 0 9
  • 1.項(xiàng)目經(jīng)驗(yàn) 2.基礎(chǔ)問題 3.指南認(rèn)識(shí) 4.解決思路 ios開發(fā)三大塊: 1.Oc基礎(chǔ) 2.CocoaTouch...
    陽光的大男孩兒閱讀 5,012評(píng)論 0 13
  • 失去的語言 天涼好個(gè)秋啊 詩人說 ...
    忍冬寒閱讀 586評(píng)論 8 6