天天看點

黑馬程式員——OC基礎學習(五)---分類(Category),代碼塊Block和protocol代理設計模式

------  <a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="blank">Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練</a> 期待與您交流! -------

     分類(Category),代碼塊Block和

     protocol代理設計模式學習總結

一.分類(Category)

  1.類别的概念

Category有很多種翻譯: 分類\類别\類目 (一般叫分類)
Category是OC特有的文法, 其他語言沒有的文法(類似于C#語言中的”擴充方法”和”partial”關鍵字)

  2.分類(Category)聲明和實作 

(1)聲明和實作一個類别
在.h檔案中,聲明類别:

@interface ClassName (CategoryName)NewMethod; //在類别中添加方法

                                             //不允許在類别中添加變量

@end 
說明:
聲明類别格式
1)新添加的方法必須寫在 @interface 與
2)ClassName 現有類的類名(要為哪個類擴充方法)
3)CategoryName 待聲明的類别名稱
4)NewMethod 新添加的方法
注意:不允許在聲明類别的時候定義變量 

在.m檔案中(也可以在.h中實作),實作類别:

@implementation ClassName(CategoryName)NewMethod

{

  ......

}

@end
說明:
    實作類别格式
1)新方法的實作必須寫在@ implementation與@end之間
2)ClassName 現有類的類名
3)CategoryName 待聲明的類别名稱
4)NewMethod 新添加的方法的實作
注:也可通過圖形界面生成類别
(2)調用類别中的方法
    與一般成員方法調用形式,完全一樣需要包含類别的頭檔案 

  3.分類的使用注意事項 

1)分類隻能增加方法,不能增加成員變量@property(可能編譯不報錯,但是運作有問題) 
2)分類可以通路原來類中的成員變量 
3)如果分類和原來類出現同名的方法,優先調用分類中的方法,原來類中的方法會被忽略 
注:分類的編譯順序為:最下面的是最後編譯,當多個分類中有同名方法,則執行最後編譯的檔案方法 

  4.分類(Category)非正式協定

非正式協定就是給NSObject類建立的類目(分類)又叫做非正式協定, 

非正式協定一般不需要進行實作,一般在子類中進行方法的重寫。 

  5.分類(Category)延展 

(1)類的延展的概念
延展類别又稱為擴充(Extendsion)
Extension是Category的一個特例其名字為匿名(為空),并且新添加的方法一定要予以實作。(Category沒有這個限制)
@interface Student ()
@end 
(2)延展的實作

通過延展來實作方法的私有,延展的頭檔案獨立。這種方法不能實作真

正的方法私有,當在别的檔案中引入延展的頭檔案,那麼在這個檔案中

定義的類的對象就可以直接調用在延展中定義所謂私有的方法 

// 對類的延展 - 隐藏方法 wrap的一種手段(非強制).h檔案

@interface SceneManager ()

+ (void) wrap;

@end

.m類的實作檔案中@implementation SceneManager+ (void) wrap {

NSLog(@"method of wrap");

}

@end

調用

[SceneManager wrap];
// 這裡會抱一個警告:Class method of "+ wrap" not found
// 不過雖然是警告,不過運作是正常的,不過這麼寫在自我規範上不好,
   即使編譯器沒有做強制限制,我們自己也要限制自己。
// 不然,延展方法就毫無意義可言。 
          注:還可通過界面建立延展 

二.代碼塊Block

  1.block的基本概念 

Block對象是一個C級别的文法和運作機制。它與标準的C函數類似,

不同之處在于,它除了有可執行代碼以外,它還包含了與堆、棧内

存綁定的變量。是以,Block對象包含着一組狀态資料,這些資料在

程式執行時用于對行為産生影響。

你可以用Block來寫一些可以傳到API中的函數語句,可選擇性地

存儲,并可以使用多線程。作為一個回調,Block特别的有用,因

為block既包含了回調期間的代碼,又包含了執行期間需要的資料。

由于Objective-C 和 C++ 都是衍生自 C,block被設計為可同時相容這三種語言。 

  2.block的基本用法

           用^操作符來聲明一個Block變量,并指明Block述句的開始。Block的主體部分

               包含在 {}内,像下面的例子中一樣(與C文法一樣,“;”指明語句的結束): 

黑馬程式員——OC基礎學習(五)---分類(Category),代碼塊Block和protocol代理設計模式
1) block最簡單形式
定義格式:
void (^block名)() = ^{代碼塊;} 
使用格式:
block名(); 
2) block帶有參數的block的定義和使用格式:
void (^block名稱)(參數清單)
= ^ (參數清單) { // 代碼實作; } 
3) 帶有參數和傳回值的block格式:
傳回類型 (^block名稱)(參數清單)
= ^ 傳回類型 (參數清單) { // 代碼實作; } 

   3.block的typedef 

        利用typedef定義block類型(和指向函數的指針很像)
格式:
typedef 傳回值類型 (^block變量名)(參數類型清單);
Typedef int(^MyBlock)(int ,int);
速記符:以後就可以利用這種類型來定義block變量了。 

  4.block通路外部變量

1)在block内部可以通路block外部的變量

在block内部可以變量,但是注意,這是一個新的記憶體空間變量 

block内部也可以定義和block外部的同名的變量(局部變量),此時局部變量會暫時屏蔽外部變量的作用域 

2)在block内部不可以修改block外部的變量

預設情況下,Block内部不能修改外部的局部變量 

給局部變量加上__block關鍵字,則這個局部變量可以在block内部進行修改。 

  5.block作為函數的傳回值

         步驟:

               1)使用typedef 定義一個新的類型 

               2)使用新類型作為函數的傳回值 

               3)定義變量接收函數傳回的值(block類型)

               4)調用block 

  6.block使用技巧及注意

1) block 結構的快速提示利用
2) block變量用作方法的參數的時候最好把參數類型清單部分加上具體的形參名 

三.protocol代理設計模式

  1.protocol概念及基本使用 

(1)protocol的基本概念 

在寫java的時候都會有接口interface這個概念,接口就是一堆方法

的聲明沒有實作,而在OC 裡面,Interface是一個類的頭檔案的聲明,

并不是真正意義上的接口的意思,在OC中,接口是由 一個叫做協定

的protocol來實作的。 

這個裡面可以聲明一些方法,和java不同的是,它可以聲明一些必須

實作的方法和選擇實作 的方法。這個和java是完全不同的。 

(2)protocol的使用流程 
協定的使用流程: 

定義協定----> 在類中采用指定的協定 ---->實作協定中的方法

(注意方法有必須實作和選擇實作兩種)

1)定義協定 
協定的定義 
@protocol 協定名稱 <NSObject> //預設遵NSObject協定 
//方法聲明清單 
@end; 
注意: 協定預設的要采納NSObject的協定 
2)采納協定 
類遵守協定 
   建立類的時候遵守某個或者某幾個協定
@interface 類名 : 父類 <協定名稱> @end 
//預設遵守NSObject協定 
@interface 類名 : 父類 <協定名稱1,協定名稱2> @end 
某個協定也遵守某個或者某些協定,一個協定可以遵守其他多個協定 
1>協定遵守協定 
@protocol 協定名稱 <其他協定名稱> 
@end 
2>多個協定之間用逗号 , 隔開。 
@protocol 協定名稱 <其他協定名稱1, 其他協定名稱2> @end 
3)實作協定中的方法 

  2.protocol的基本使用 

1)定義協定 
協定的定義 
@protocol 協定名稱 <NSObject> 
//方法聲明清單 
@end; 
注意: 協定預設的要采納NSObject的協定
2)采納協定 
注意:采納協定要先把要采納的協定引入過來 
1>類遵守協定 : 某個類遵守某個協定 
2>協定遵守協定 
@protocol 協定名稱 <其他協定名稱> @end; 
3)實作協定中的方法 
如果一個類遵守了某個協定 則隻需要在這個類的實作(.m)檔案中,實作協定的方法就可以了 
注:也使用圖形界面建立協定

  3.OC中的協定(protocol)使用注意: 

1)Protocol:就一個用途,用來聲明一大堆的方法(不能聲明成員變量),不能寫實作。 
2)隻要某個類遵守了這個協定,就擁有了這個協定中的所有方法聲明。 
3)隻要父類遵守了某個協定,那麼子類也遵守。 
4)Protocol聲明的方法可以讓任何類去實作,protocol就是協定。 
5)OC不能繼承多個類(單繼承)但是能夠遵守多個協定。繼承(:),遵守協定(< >) 
6)基協定:<NSObject>是基協定,是最根本最基本的協定,其中聲明了很多最基本的方法。 
7)協定可以遵守協定,一個協定遵守了另一個協定,就可以擁有另一份協定中的方法聲明 
注: 1)協定之間可以有繼承關系 
    2)類如果采納協定後,實作了協定的方法,這些方法可以被子類繼承 

  4.protocol基協定介紹 

NSObject是一個基類,最根本最基本的類,任何其他類最終都要繼承它,它

還有名字也叫 NSObject的協定,它是一個基協定,最根本最基本的協定 

NSObject協定中聲明很多最基本的方法 description 
     retain
     release
建議每個新的協定都要遵守NSObject協定

  5.protocol中@required和@optional 

@required和@optional是協定方法聲明中的兩個關鍵字他們主要用于控制方法

是否要實作(預設是@required),在大多數情況下,用途在于程式員之間的交流 

@public
@protected
@private
@package
@required:這個方法必須要實作(若不實作,編譯器會發出警告) 
@optional這個方法不一定要實作 

  6. protocol類型限制 

1)使用id存儲對象時,對象的類型限制 
格式:id <協定名稱> 變量名 
2)對象指派時類型限制 使用類也同樣如此 
格式:類名<協定名稱> *變量名 
3)對象關聯關系下,對象的類型限制

  7.id和instancetype的差別 

id和instancetype的差別: 
1)instancetype隻能作為函數或者方法的傳回值 
2)id能作為方法或者函數的傳回值、參數類型,也能用來定義變量 
3)instancetype對比id的好處 
  * 能精确地限制傳回值的具體類型 

  8.protocol代理設計模式引入 

代理模式是在oc中經常遇到的一種設計模式,那什麼叫做代理模式呢? 

舉個例子:有一個嬰兒,他本身不會自己吃飯和洗澡等等一些事情,于

是嬰兒就請了一個保姆,于是嬰兒和保姆之間商定了一個協定,協定

中寫明了保姆需要做什麼事情, 而保姆就是這個代理人, 即:嬰兒和

保姆之間有個協定,保姆遵守該協定,于是保姆就需要實作該協定中

的條款成為代理人。

  9. protocol代理設計模式概念 

代理模式概念
傳入的對象,代替目前類完成了某個功能,稱為代理模式
利用協定實作代理模式的主要思路為:

1)定義一個協定,裡面聲明代理類需要實作的方法清單, 

  比如這裡一個代理類需要實作feedBaby與HongSleep方法

2)建立一個代理類(比如BaoMu),遵守上面的代理協定 
3)在需要代理的類中(Baby),定義一個對象類型為id且遵守代理協定的成員變量 
4)在Baby類中調用成員變量_delegate(代理)的方法,調用代理類的方法 
5)main.m或其他使用Baby類的檔案中,為Baby類的成員變量(代理類)指派 

  10.protocol代理模式應用場合 

代理設計模式的場合:
* 當對象A發生了一些行為,想告知對象B 

(讓對象B成為對象A的代理對象)
* 對象B想監聽對象A的一些行

為(讓對象B成為對象A的代理對象)
* 當對象A無法處理某些行為

的時候,想讓對象B幫忙處理 (讓對象B成為對象A的代理對象) 

1)監聽器的場合
* Teacher想監聽Baby的一些行為 
2)通知的場合
* Baby發生了一些行為,想告知Teacher 
3)有些事情,不想自己處理,想交給别人處理
* Baby發生了一些
  行為, 但是自己不會處理, 可以交給Teacher處理