OC加強day03
分類的簡單使用
- 什麼是分類
- 當一個類包含了非誠多的術語不同範疇的方法的時候 我們通常將這個類分爲多個文件來實現,其中一個類叫主類/本類其餘的叫分類
- 有了分類之後 一個類 = 所有分類 + 本類
- 如何添加分類
- newFile–> 選中OC File–>選擇category—>填寫分類名,本類名
- 分類的聲明
@interface 本類名 (分類名)
@end
@implementation 本類名 (分類名)
@end
* 分類的使用注意*
- 在分類中不能寫屬性,只能寫方法的聲明和實現
- 在分類中用@property也是可以的
- 但是即使使用了 @property 也不會生成屬性,只會生成getter和getter方法的聲明(不包含實現)
- 在分類中可不可以訪問本類的中的屬性? 可以
- 在分類中 不能直接訪問本類中的真私有屬性,但是通過getter各setter方法來訪問本類的真私有屬性
- 本類中的方法和本類的方法能不能同名? 可以
- 這個時候 不管有沒有引入分類 都會調用分類的方法
- 如果多個分類中有同名的方法 只會調用最後邊編譯的那個分類中的方法
- 怎麼看那個分類是最後編譯的?
選中項目—>選中Target—>Build Phase–>編譯源(Compile Source)–>在此修改順序即可
- 總結: 分類的使用場景
- 團隊開發對個人共同寫一個類的時候
- 當一個類方法非常多的 功能複雜的時候
非正式協議
- 其實非正式協議就是一個分類,是爲系統類添加的分類
延展的基本使用
- 延展是什麼?
- 一個特殊的分類:
- 是一個匿名的分類(就是一個分類沒有名字)
- 在延展中可以有屬性,但是隻有方法的聲明,而沒有方法的實現(方法的實現在本類的.m文件中)
- 如何寫一個延展
@interface 本類名 () // 小括號中什麼都不寫 就是延展
@end
- 注意:延展沒有實現,和本類共同用一個實現
- 延展的使用注意
- 普通的分類(有名字):
- 不能寫屬性,可以寫方法的聲明和實現。
- 普通分類中可以使用@property,只會生成方法的聲明
- 延展(沒有名字)
- 可以寫屬性,可以有方法的聲明,延展的實現在本類中
- 延展中可以使用@property,會有屬性也會有方法的聲明和實現
- 普通的分類(有名字):
延展的基本使用
- 延展的作用: 生成私有的@property和私有方法
- @property 會生成屬性,方法的聲明,方法實現
- 什麼是私有的@property? 就是生成的屬性,方法的聲明和實現都不讓外界訪問
- 怎麼辦?
- 在.m中 可以寫一個延展,然後把@property 寫到延展裏 這樣生成的_屬性名,getter和setter方法的聲明都在.m文件中
- 延展如何使用?
- 大部分的情況下,延展都會寫在本類的.m文件中,而且是寫到最上面
- 然後可以在延展中寫屬性的方法,這些屬性和方法都是私有的成員
- 總之:
- 延展就是用來私有化成員的,只要你想寫一個私有的成員(屬性,方法)
- 寫到延展中
block變量的聲明
- block是一個數據類型,它的變量可以存 一段符合要求的代碼
- block變量的聲明:
返回值類型 (^變量名)(參數列表);
xxx (^ttt)(xxx a,ooo b);
聲明瞭一個block類型的變量, 變量名字叫做ttt;
ttt可以儲存 返回值類型是 xxx 有一個xxx類型的參數 一個ooo類型的參數
block變量賦值初始化
- 寫一個block代碼塊的格式
^返回值類型(參數列表){
代碼;
}
- 寫一個代碼塊 求2個整數的和
^int(int num1,int num2){
//代碼功能就是求和
// return num1+num2;
int num3 = num1 + num2;
return num3;
};
寫一個代碼塊 求2個整數的最大值
^int(int num1,int num2){
//代碼塊 求num1,和num2中的最大值
int max = num1 > num2 ? num1 : num2;
return max;
};
3.保存上面的2個代碼塊
3.1>//第一種
int (^blockSum)(int num1,int num2);//定義了一個變量
blockSum = ^int(int num1,int num2){
//代碼功能就是求和
// return num1+num2;
int num3 = num1 + num2;
return num3;
};
//第二種
int (^blockSum)(int num1,int num2) = ^int(int num1,int num2){
//代碼功能就是求和
// return num1+num2;
int num3 = num1 + num2;
return num3;
};
3.2>//第一種
int (^blockMax)(int num1,int num2);//定義了一個變量
blockMax = ^int(int num1,int num2){
//代碼塊 求num1,和num2中的最大值
int max = num1 > num2 ? num1 : num2;
return max;
};
//第二種
int (^blockMax)(int num1,int num2) = ^int(int num1,int num2){
//代碼塊 求num1,和num2中的最大值
int max = num1 > num2 ? num1 : num2;
return max;
};
- 執行block變量中的代碼
- 格式:
- block變量名字(實參列表)
- 需要參數就穿進去
- 如果有返回值 就接收
- 格式:
block 使用 typedef的簡化 定義
- typedef 的作用是?
- 爲一個已經存在的數據類型,起一個 別名
- 使用typedef簡化block的定義
- typedef的基本使用
typedef long int Lint;
int nums1[4];//int[4] nums1;
int nums2[4];//int[4] nums2;
typedef int NUM[4];
NUM nums3;//等價於 int nums3[4];
- typedef簡化block的定義
“`
void (^blockName)(int,int);
//void (^)(int,int) blockName;==>XXX a;
語法格式:
// typedef void (^)(int,int) NewType;
typedef 返回值類型 (^新類型名字)(參數列表);
typedef void (^NewType)(int,int);
這個NewType就是新類型的名字
就可以通過NewType 來定義block變量
NewType block1,block2;
**block訪問外部變量的問題**
- block代碼段內部,可以定義和玩不變量名字相同的變量
- 在block代碼段的內部
- 可以訪問外部的全局變量和局部變量的值
- 可以修改全局變量和自己的局部變量的值 但是不能修改外部局部變量的值
- 如果非要修改 就子啊外部的局部變量的值 定義的時候前面加上 __block修飾
**block作爲函數的參數**
- block作爲函數的參數的寫法
void test(返回值類型 (^變量名)(參數列表1,參數列表2))
{
}
//第二種
typedef void (^NewType)(int num1,int num2);
void test(NewType block1)
{
}
- 在函數內部如何執行block代碼
typedef void(^NewType)(int num1, int num2)
void tese(NewType block1)
{
block1(有參數寫參數 沒參數拉倒)
//有返回值就接收
}
- 調用這個函數的終極方法
1>定義一個block變量 給他賦值
NewType block2 = ^void(int num1,int num2){
int num3 = num1 + num2;
NSLog(@"num3 = %d",num3);
};
2>調用函數
test(block2);
3>終極版
test(^void(int num1,int num2){
int num3 = num1 + num2;
NSLog(@"num3 = %d",num3);
});//有一個小技巧,調用函數的時候 如果需要傳遞代碼塊,只需要敲回車鍵,自動添加代碼塊的格式
- "注意:定義block變量的時候,block內的代碼不會執行
"block內的代碼只有在調用block的時候才執行
4.例子:
1>寫一個函數模擬 下載數據 解析數據 並且調用視頻播放器播放
2>寫一個函數模擬 下載音頻 解析數據 並且調用音樂播放器播放