一诅蝶、延展
延展: Extension
1). 是一個特殊的分類,所以延展也是類的一部分
2). 特殊之處:
a. 延展這個特殊的分類沒有名字
b. 只有聲明沒有實現(xiàn)亚隙,和本類共享一個實現(xiàn)-
延展的語法
語法:
@interface 本類名 ()
@end沒有實現(xiàn),和本類共享一個實現(xiàn).
為類添加延展步驟
New File->FileType選擇Extension
只有一個.h文件按咒,文件名:本類名_取的文件名.h
這個文明中只有聲明
@interface Person ()
@end延展的基本使用
1). 延展的本質(zhì)是一個類紊选,作為本類的一部分
只不過是一個特殊的分類亥宿,沒有名字
2). 延展只有聲明利凑,沒有單獨的實現(xiàn)浆劲,和本類共享一個實現(xiàn)延展和分類的區(qū)別
1). 分類有名字,延展沒有名字哀澈,是一個匿名的分類
2). 每一個分類都有單獨的聲明和實現(xiàn)牌借,而延展只有聲明,沒有單獨的實現(xiàn)割按,和本類共享一個實現(xiàn)
3). 分類中只能新增方法膨报,而延展中任意的成語都可以寫
4). 分類中可以寫@property但是只會生成getter/setter聲明,延展中寫@property會自動生成私有屬性适荣,也會生成getter/setter的聲明和實現(xiàn)延展的應用場景
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
OC在C的基礎上新增了一些數(shù)據(jù)類型
BOOL/Boolean/class/nil/SEL/id/blockblock是一個數(shù)據(jù)類型
既然是一個數(shù)據(jù)類型寥袭,那么就可以聲明這個數(shù)據(jù)類型的變量
1). block是一個數(shù)據(jù)類型路捧,所以我們可以聲明一個block類型的變量
2). block類型的變量中專門存儲一段代碼关霸,可以有參數(shù),可以有返回值.-
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變量中就只能存儲這樣的代碼了见剩,其他格式的代碼段無法存儲 -
初始化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變量的要求,否則就會報錯. 如何執(zhí)行存儲在block變量中的代碼
語法格式: block變量名();
有參數(shù)就傳參數(shù),有返回值就接.-
關于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代碼段,因為這樣可以提高代碼段的閱讀性.
typedef簡化block
1). 定義block類型長的問題
2). typedef的使用場景:講一個長類型定義為短類型
3). 使用typedef將長的block類型定義為一個短類型
typedef 返回值類型 (^新類型)(參數(shù)列表)
typedef void (^NewType)();
代表重新定義了一個類型叫做NewType弃衍,是一個block類型呀非,無參數(shù)無返回值的block類型.關于block塊訪問外部變量的問題
1). 在block代碼塊的內(nèi)部可以取定義在外部的變量的值,定義在外部的局部變量和全局變量
2). 可以修改全局變量的值,不能修改局部變量的值.
3). 如果你希望我們定義的局部變量可以允許在block代碼塊的內(nèi)部去修改岸裙,那么就為這個局部變量加1個__block的修飾符.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定義的短語句block與函數(shù)
相同點:都是封裝一段代碼
不同點:
1). block是一個數(shù)據(jù)類型降允,函數(shù)是一個函數(shù)
2). 我們可以聲明block類型的變量恩闻,函數(shù)就只是函數(shù)
3). block可以作為函數(shù)的參數(shù).
三、協(xié)議
協(xié)議: protocol.
作用: 專門用來聲明一大堆方法(不能聲明屬性剧董,也不能實現(xiàn)方法幢尚,只能用來寫方法的聲明).
只要某個類遵守了這個協(xié)議,就相當于擁有這個協(xié)議中的所有的方法聲明.-
協(xié)議的聲明
@protocol 協(xié)議名稱 <NSObject>
方法的聲明;
@end新建一個協(xié)議的方式, NewFile->OC-File-protocol
協(xié)議的文件名:.h 并且只有一個.h文件在協(xié)議中翅楼,只能用來聲明方法
作用: 專門用來寫方法聲明的 -
類遵守協(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é)議中的方法的時候就會報錯.
-
類是單繼承犹菇,但是協(xié)議可以多遵守
一個類值能有一個父類美浦,但是一個類可以遵守多個協(xié)議
@interface 類名 : 父類名 <協(xié)議名稱1, 協(xié)議名稱2...>@end
當一個類遵守了多個協(xié)議之后,就相當于這個類擁有了所有協(xié)議中定義的方法的聲明项栏,那么這個類蹬竖,就應該實現(xiàn)所有協(xié)議中的方法 -
@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.
-
協(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é)議繼承. -
@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é)議中的方法.