Objective-C 學習第八天

一诅蝶、延展

  1. 延展: Extension
    1). 是一個特殊的分類,所以延展也是類的一部分
    2). 特殊之處:
    a. 延展這個特殊的分類沒有名字
    b. 只有聲明沒有實現(xiàn)亚隙,和本類共享一個實現(xiàn)

  2. 延展的語法
    語法:
    @interface 本類名 ()
    @end

    沒有實現(xiàn),和本類共享一個實現(xiàn).

  3. 為類添加延展步驟
    New File->FileType選擇Extension
    只有一個.h文件按咒,文件名:本類名_取的文件名.h
    這個文明中只有聲明
    @interface Person ()
    @end

  4. 延展的基本使用
    1). 延展的本質(zhì)是一個類紊选,作為本類的一部分
    只不過是一個特殊的分類亥宿,沒有名字
    2). 延展只有聲明利凑,沒有單獨的實現(xiàn)浆劲,和本類共享一個實現(xiàn)

  5. 延展和分類的區(qū)別
    1). 分類有名字,延展沒有名字哀澈,是一個匿名的分類
    2). 每一個分類都有單獨的聲明和實現(xiàn)牌借,而延展只有聲明,沒有單獨的實現(xiàn)割按,和本類共享一個實現(xiàn)
    3). 分類中只能新增方法膨报,而延展中任意的成語都可以寫
    4). 分類中可以寫@property但是只會生成getter/setter聲明,延展中寫@property會自動生成私有屬性适荣,也會生成getter/setter的聲明和實現(xiàn)

  6. 延展的應用場景
    1). 要為類寫一個私有的@property
    生成的getter/setter只能在類的內(nèi)部訪問,不能在外部訪問
    其實现柠,只讓@property生成私有屬性、生成getter/setter方法的實現(xiàn).
    2). 延展100%的情況下不會獨占一個文件弛矛,都是將延展直接寫在本類的實現(xiàn)文件當中晒旅,這個時候,寫在延展中的成員汪诉,就相當于這個類的私有成員,外部無法訪問谈秫,只能在本類的實現(xiàn)中訪問
    3). 當我們想為類定義私有成員的時候扒寄,就可以使用延展,將延展定義在這個類的實現(xiàn)當中.雖然可以定義在@implementation中拟烫,但是不要這么寫该编,這樣不規(guī)范,寫一個延展硕淑,定義在延展當中课竣。
    *. 如果要為類寫一個私有方法,建議將聲明寫在延展當中置媳,實現(xiàn)寫在本類的實現(xiàn)中
    *. 如果想要為類寫一個私有的@property于樟,就直接寫在延展中
    4). 延展天生就是來私有化類的成員
    如果類的成員只希望在類的內(nèi)部訪問,那么就將其定義在嚴重中拇囊,如果類的成員允許被外界訪問迂曲,定義在本類的@interface中

二、block

  1. OC在C的基礎上新增了一些數(shù)據(jù)類型
    BOOL/Boolean/class/nil/SEL/id/block

  2. block是一個數(shù)據(jù)類型
    既然是一個數(shù)據(jù)類型寥袭,那么就可以聲明這個數(shù)據(jù)類型的變量
    1). block是一個數(shù)據(jù)類型路捧,所以我們可以聲明一個block類型的變量
    2). block類型的變量中專門存儲一段代碼关霸,可以有參數(shù),可以有返回值.

  3. block變量的聲明
    1). 雖然block變量中是用來存儲一段代碼的杰扫,但是一個block變量中并不是任意的一段代碼都可以存進去的队寇,而是有限定的。在聲明block變量的時候章姓,必須要指定這個block變量存儲的代碼是否有參數(shù)佳遣,是否有返回值,一旦指定以后啤覆,這個block變量中就只能存儲這樣的代碼了.

    聲明了一個block變量苍日,返回值是void,參數(shù)是一個int類型的窗声,這個block變量中就只能存儲無返回值相恃,并且有一個int參數(shù)的代碼段.
    2). 聲明block變量的語法格式:
    返回值類型 (^block變量的名稱)(參數(shù)列表);
    void (^myBlock1)(); 表示聲明了一個block類型的變量,叫做myBlock1笨觅,這個變量中只能存儲沒有返回值沒有參數(shù)的代碼段.
    3). 最重要
    聲明block變量的時候要指定這個block變量可以存儲的代碼段的返回值和參數(shù)描述拦耐,一旦指定,這個block變量中就只能存儲這樣的代碼了见剩,其他格式的代碼段無法存儲

  4. 初始化block變量
    1). 原理: 寫一個符合block要求的代碼段杀糯,存儲到block變量中就可以了
    2). 代碼段的書寫格式:
    ^返回值類型(參數(shù)列表){
    代碼段;
    };
    3). 寫一個無參數(shù)無返回值的代碼段:
    這個時候我們將這段代碼使用賦值符號存儲到無返回值無參數(shù)要求的block變量中.

        void (^myBlock1)();
        ^void(){
            NSLog(@"我");
            NSLog(@"我");
        };
    
        等價于
        void (^myBlock1)();
        myBlock1 = ^void(){
                        NSLog(@"我");
                        NSLog(@"我");
                    };
        還等價于
        void (^myBlock1)() = ^void(){
                                NSLog(@"我");
                                NSLog(@"我");
                            };
    

    4). 有返回值的代碼段.
    我們可以將這段代碼賦值給符合要求的block變量.

        int (^myBlock2)();
        myBlock2 = ^int(){
                        int num1 = 10 + 20;
                        return num1;
                    };
    

    5). 既有參數(shù)又有返回值的代碼段.

        int (^myBlock3)(int num1, int num2);
        myBlock3 = ^int(int num1, int num2){
                        int num3 = num1 + num2;
                        return num3;
                    };
    

    6). 注意
    賦值給block變量的代碼段必須要符合block變量的要求,否則就會報錯.

  5. 如何執(zhí)行存儲在block變量中的代碼
    語法格式: block變量名();
    有參數(shù)就傳參數(shù),有返回值就接.

  6. 關于block簡寫
    1). 如果我們寫的代碼段沒有返回值苍苞,那么代碼段的void可以省略

        void (^myBlock1)() = ^(){
                                NSLog(@"我");
                                NSLog(@"我");
                            };
    

    注意: 代碼段的返回值如果是void可以省略固翰,聲明block變量的返回值不能省略.
    2). 如果我們寫的代碼段沒有參數(shù),那么代碼段的小括弧可以省略

        int (^myBlock2)();
        myBlock2 = ^int{
                        int num1 = 10 + 20;
                        return num1;
                    };
    

    強調(diào): 指的是代碼段
    所以羹呵,當一個代碼段既沒有參數(shù)也沒有返回值的時候骂际,就只寫^

        void (^myBlock1)() = ^
        {
                                NSLog(@"我");
                                NSLog(@"我");
                            };
    

    3). 聲明block變量的時候,如果有指定的參數(shù)冈欢,可以只寫參數(shù)的類型而不寫參數(shù)名稱

        int (^myBlock3)(int, int);
        myBlock3 = ^int(int num1, int num2){
                        int num3 = num1 + num2;
                        return num3;
                    };
    

    注意: 聲明block的時候可以省略歉铝,在寫代碼段的時候類型和名城管都要寫
    4). 無論代碼段是否有返回值,在寫代碼的時候都可以省略

        int (^myBlock3)(int, int);
        myBlock3 = ^(int num1, int num2){
                        int num3 = num1 + num2;
                        return num3;
                    };
    

    如果代碼段中沒有返回任何數(shù)據(jù)凑耻,那么它會認為代碼段是沒有返回值的太示,如果代碼中有返回數(shù)據(jù),返回的數(shù)據(jù)什么類型香浩,它就會認為這個代碼段是什么類型.

    建議: 不要簡寫类缤,仍然按照最標準的寫法來寫block變量和block代碼段,因為這樣可以提高代碼段的閱讀性.

  7. typedef簡化block
    1). 定義block類型長的問題
    2). typedef的使用場景:講一個長類型定義為短類型
    3). 使用typedef將長的block類型定義為一個短類型
    typedef 返回值類型 (^新類型)(參數(shù)列表)
    typedef void (^NewType)();
    代表重新定義了一個類型叫做NewType弃衍,是一個block類型呀非,無參數(shù)無返回值的block類型.

  8. 關于block塊訪問外部變量的問題
    1). 在block代碼塊的內(nèi)部可以取定義在外部的變量的值,定義在外部的局部變量和全局變量
    2). 可以修改全局變量的值,不能修改局部變量的值.
    3). 如果你希望我們定義的局部變量可以允許在block代碼塊的內(nèi)部去修改岸裙,那么就為這個局部變量加1個__block的修飾符.

  9. block是一個數(shù)據(jù)類型猖败,作為函數(shù)參數(shù)
    1). 如何為函數(shù)定義block類型的參數(shù)
    a. 在小括弧中聲明一個指定格式的block變量
    b. 調(diào)用的時候可以直接將符合要求的代碼段傳遞過去
    c. 通過Xcode提示可以快速的生產(chǎn)block代碼段
    2). block作為參數(shù)可以實現(xiàn)的效果
    可以將調(diào)用者自己寫的代碼傳遞到函數(shù)的內(nèi)部執(zhí)行
    3). block作為函數(shù)的返回值返回
    當將block作為函數(shù)的返回值的時候,返回值的類型就必須要使用typedef定義的短語句

  10. block與函數(shù)
    相同點:都是封裝一段代碼
    不同點:
    1). block是一個數(shù)據(jù)類型降允,函數(shù)是一個函數(shù)
    2). 我們可以聲明block類型的變量恩闻,函數(shù)就只是函數(shù)
    3). block可以作為函數(shù)的參數(shù).

三、協(xié)議

  1. 協(xié)議: protocol.
    作用: 專門用來聲明一大堆方法(不能聲明屬性剧董,也不能實現(xiàn)方法幢尚,只能用來寫方法的聲明).
    只要某個類遵守了這個協(xié)議,就相當于擁有這個協(xié)議中的所有的方法聲明.

  2. 協(xié)議的聲明
    @protocol 協(xié)議名稱 <NSObject>
    方法的聲明;
    @end

    新建一個協(xié)議的方式, NewFile->OC-File-protocol
    協(xié)議的文件名:.h 并且只有一個.h文件

    在協(xié)議中翅楼,只能用來聲明方法
    作用: 專門用來寫方法聲明的

  3. 類遵守協(xié)議
    如果想讓一個類擁有協(xié)議中定義的所有的方法聲明尉剩,那么就讓這個類遵守這個協(xié)議,類只要遵守這個協(xié)議毅臊,那么這個類就擁有了這個協(xié)議中定義的所有的方法的聲明了.
    @interface 類名 : 父類名 <協(xié)議名稱>

    @end
    :表示繼承
    <> 表示遵守的協(xié)議

    當一個類理茎,遵守了一個協(xié)議,那么就相當于這個類擁有了協(xié)議中定義的所有的方法的聲明管嬉,這個類只是擁有了這個協(xié)議中的聲明而已皂林,沒有實現(xiàn),所以蚯撩,這個類础倍,就應該實現(xiàn)協(xié)議中的方法.

    如果類不實現(xiàn)協(xié)議中的方法,也不會報錯胎挎,只是編譯器會報警告沟启,但是當創(chuàng)建對象,來調(diào)用 這個沒有的實現(xiàn)的協(xié)議中的方法的時候就會報錯.

  4. 類是單繼承犹菇,但是協(xié)議可以多遵守
    一個類值能有一個父類美浦,但是一個類可以遵守多個協(xié)議
    @interface 類名 : 父類名 <協(xié)議名稱1, 協(xié)議名稱2...>

    @end
    當一個類遵守了多個協(xié)議之后,就相當于這個類擁有了所有協(xié)議中定義的方法的聲明项栏,那么這個類蹬竖,就應該實現(xiàn)所有協(xié)議中的方法

  5. @required 與 @optional
    在協(xié)議當中,如果方法的聲明被@required修飾币厕,那么這個協(xié)議的類就必須要實現(xiàn)這個方法,否則編譯器會發(fā)出警告.
    在協(xié)議當中旦装,如果方法的聲明被@optional修飾页衙,那么遵守這個協(xié)議的類可以實現(xiàn)這個方法店乐,也可以不實現(xiàn)這個方法,不實現(xiàn)編譯器也不會報警告.

    無論@required與@optional都可以不實現(xiàn)眨八,編譯器不會報錯腺兴,仍然可以編譯運行,唯一的區(qū)別:當遵守協(xié)議的類不實現(xiàn)協(xié)議中的方法的時候廉侧,@required會給出一個警告,@optional警告都沒有段誊,默認是@required.

  6. 協(xié)議可以從另外一個類繼承闰蚕,也可以多繼承.
    協(xié)議可以繼承另外一個協(xié)議,A協(xié)議繼承B協(xié)議连舍,那么A協(xié)議中不僅有自己的方法的聲明没陡,還有B協(xié)議中的方法的聲明。如果有一個類遵守了A協(xié)議烟瞧,那么這個類就擁有了A诗鸭、B協(xié)議中所有方法的聲明.

    協(xié)議之間繼承的語法格式
    @protocol A協(xié)議名稱 <B協(xié)議名稱>

    @end
    代表A協(xié)議繼承自B協(xié)議,A協(xié)議中既有自己方法的聲明参滴,也有B協(xié)議中的方法聲明强岸。要求所有的協(xié)議直接或者間接的從NSObject基協(xié)議繼承.

  7. @protocol類型限制
    1). 這個指針指向遵守了指定協(xié)議的任意對象,否則就會報警告
    NSObject<協(xié)議名稱> *指針名;
    id<協(xié)議名稱> *指針名;
    2). 聲明一個指針變量砾赔,要求這個指針變量指向的對象必須遵守多個協(xié)議
    NSObject<協(xié)議名稱1, 協(xié)議名稱2> *指針名;
    id<協(xié)議名稱1, 協(xié)議名稱2> *指針名;

    3). 定義一個指針蝌箍,指向遵守了學習協(xié)議的學生對象.
    Student<StudyProtocol> *stu = [Student new];
    4). 為什么
    a. 遵守了某個協(xié)議的類,就相當于這個類擁有了這個協(xié)議所定義的行為
    b. 因為要調(diào)用對象中的協(xié)議方法,只有遵守了這個協(xié)議暴心,才能有協(xié)議中的方法.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妓盲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子专普,更是在濱河造成了極大的恐慌悯衬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件檀夹,死亡現(xiàn)場離奇詭異筋粗,居然都是意外死亡,警方通過查閱死者的電腦和手機炸渡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門娜亿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚌堵,你說我怎么就攤上這事买决∨嬗ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵督赤,是天一觀的道長嘁灯。 經(jīng)常有香客問我,道長够挂,這世上最難降的妖魔是什么旁仿? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮孽糖,結(jié)果婚禮上枯冈,老公的妹妹穿的比我還像新娘。我一直安慰自己办悟,他們只是感情好尘奏,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著病蛉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俗孝。 梳的紋絲不亂的頭發(fā)上魄健,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天沽瘦,我揣著相機與錄音,去河邊找鬼良哲。 笑死助隧,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的漏健。 我是一名探鬼主播橘霎,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼姐叁,長吁一口氣:“原來是場噩夢啊……” “哼外潜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嘱吗,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤谒麦,失蹤者是張志新(化名)和其女友劉穎哆致,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耻蛇,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡臣咖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年夺蛇,在試婚紗的時候發(fā)現(xiàn)自己被綠了布疙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡截型,死狀恐怖儒溉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情波闹,我是刑警寧澤涛碑,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布蒲障,位于F島的核電站瘫证,受9級特大地震影響庄撮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毡庆,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一么抗、第九天 我趴在偏房一處隱蔽的房頂上張望厅翔。 院中可真熱鬧,春花似錦刀闷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翻默。三九已至,卻和暖如春趾牧,著一層夾襖步出監(jiān)牢的瞬間肯污,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工哄芜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柬唯,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓失晴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親师坎。 傳聞我的和親對象是個殘疾皇子胯陋,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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