什么是 Block
Block是iOS中一種比較特殊的數(shù)據(jù)類型-
Block是蘋果官方特別推薦使用的數(shù)據(jù)類型,應(yīng)用場(chǎng)景比較廣泛- 動(dòng)畫(huà)
- 多線程
- 集合遍歷
- 網(wǎng)絡(luò)請(qǐng)求回調(diào)
-
Block的作用- 用來(lái)保存某一段代碼,可以在恰當(dāng)?shù)臅r(shí)間再取出來(lái)調(diào)用
- 功能有點(diǎn)類似于函數(shù)和方法
- 可以保存代碼
- 有返回值
- 有形參
標(biāo)志:
^
- 沒(méi)有返回值,沒(méi)有形參
void (^JuneBlock)() = ^(){};
// 如果block沒(méi)有形參,可以省略后面的 小括號(hào)()
void (^JuneBlock)() = ^{};
- 有返回值,有形參
int (^JuneBlock)(int, int) = ^(int a, int b){
return a + b;
};
- typedef 定義
Block
// 定義一個(gè)叫 MyBlock 的類型
// 利用 MyBlock類型 可以定義 block變量
// 利用 MyBlock類型定義出來(lái)的變量,存儲(chǔ)的代碼必須返回 int 必須接受 2個(gè)int類型的參數(shù)
typedef int (^JuneBlock)(int, int)
JuneBlock jBlock;
JuneBlock j1, j2;
j1 = ^(int a, int b){
return a - b;
};
JuneBlock sumBlock = ^(int a, int b){
return a + b;
};
-
Block訪問(wèn)外面變量
1>Block內(nèi)部可以訪問(wèn)外面的變量
2> 默認(rèn)情況下,Block內(nèi)部不能修改外面的局部變量
3> 給局部變量加上__block關(guān)鍵字,就可以在Block內(nèi)部修改
int a = 10;
__block int b = 10;
void (^JuneBlock)() = ^{
// 默認(rèn)情況下,block 內(nèi)不能修改外面的局部變量
// a = 20;
// 因?yàn)?變量 b 前面加了__block,所以變量 b 的值可以被修改
b = 20;
NSLog(@"b is %d", b);
};
JuneBlock();
- 注意點(diǎn)
- 調(diào)用
Block之前,一定要做判斷
if(JuneBlock)
{
JuneBlock();
}
- 在定義
Block時(shí),有形參時(shí),寫上參數(shù)名稱,使用 Xcode 調(diào)此Block時(shí),會(huì)有提示,直接敲回車,快速創(chuàng)建形參代碼
Protocol 協(xié)議
- 用來(lái)聲明一大堆方法(不能聲明成員變量和實(shí)現(xiàn))
- 只要某個(gè)類遵守了這個(gè)協(xié)議,就能擁有這個(gè)協(xié)議中的所有方法聲明
- 只要父類遵守了某個(gè)協(xié)議,就相當(dāng)于子類也遵守了
- 協(xié)議可以定義在單獨(dú) .h 文件中,也可以定義在某個(gè)類中
- 如果此協(xié)議只用在某個(gè)類中,就定義在某個(gè)類中
- 如果此協(xié)議用在很多類中,就應(yīng)該定義在單獨(dú)文件中
- 分類可以定義在單獨(dú)
.h和.m中,也可以定義在原來(lái)類中- 一般情況下,都是定義在單獨(dú)文件
- 定義在原來(lái)類中的分類,要能看懂語(yǔ)法
- 協(xié)議遵守協(xié)議
- 一個(gè)協(xié)議可以遵守其他多個(gè)協(xié)議,多個(gè)協(xié)議之間用逗號(hào)
,隔開(kāi) - 一個(gè)協(xié)議遵守了另外一個(gè)協(xié)議,就擁有了另一個(gè)協(xié)議的所有方法聲明
- 一個(gè)協(xié)議可以遵守其他多個(gè)協(xié)議,多個(gè)協(xié)議之間用逗號(hào)
// 協(xié)議聲明
@protocol 協(xié)議名稱
// 方法聲明列表
@end
// 協(xié)議遵守協(xié)議
@protocol 協(xié)議名稱 <協(xié)議1, 協(xié)議2>
// 方法聲明列表
@end
// 某個(gè)類遵守協(xié)議,多個(gè)協(xié)議
@interface 類名 : 父類 <協(xié)議名,其他協(xié)議名,...>
@end
// 定義了一個(gè)名叫 JuneProtocol 的協(xié)議
@protocol JuneProtocol <NSObject>
@end
// 某個(gè)類 .h 中使用協(xié)議
@protocol 協(xié)議名;
相當(dāng)于 @class,但是具體使用時(shí),要在 .m 文件中 #import"協(xié)議類名"
-
關(guān)鍵字 : 用途在于程序員之間的交流
-
@required:要求實(shí)現(xiàn),不實(shí)現(xiàn)就會(huì)發(fā)出警告(不寫此關(guān)鍵字,默認(rèn)是要求) -
@optional:不要求實(shí)現(xiàn)
-
-
基協(xié)議
NSObject-
NSObject是一個(gè)基類,最根本最基本的類,任何其他類最終都要繼承它 - 其實(shí)還有一個(gè)協(xié)議,名字也叫
NSObject,它是一個(gè) 基協(xié)議,最根本最基本的協(xié)議 -
NSObject協(xié)議中聲明很多最基本的方法,比如description、retain、release等 - 建議每個(gè)新的協(xié)議都要遵守
NSObject基協(xié)議
-
@protocol JuneProtocol <NSObject>
@end
- 定義一個(gè)變量的時(shí)候,限定這個(gè)變量保存的對(duì)象遵守某個(gè)協(xié)議
類名<協(xié)議名> *變量名
id<協(xié)議名> 變量名
NSObject<JuneProtocol> *obj
id<JuneProtocol> obj2
// 如果沒(méi)有遵守對(duì)應(yīng)的協(xié)議,編譯器會(huì)警告
// 要求 obj 保存的對(duì)象必須是遵守 JuneProtocol 這個(gè)協(xié)議
NSObject<JuneProtocol> *obj = [[NSObject alloc] init];
id<JuneProtocol> obj = [[NSObject alloc] init];
id 相當(dāng)于 NSObject*
-
@property中聲明的屬性也可以用作一個(gè)遵守協(xié)議的限制
@property (nonatomic, weak) 類名<協(xié)議名> *屬性名;
@property (nonatomic, weak) id<協(xié)議名> 屬性名;
@property (nonatomic, weak) Vampire<JuneProtocol> *p;
@property (nonatomic, weak) id<JuneProtocol> obj;
代理設(shè)計(jì)模式
@property (nonatomic, weak) id<協(xié)議名> delegate;
本類對(duì)象.delegate = 某個(gè)類對(duì)象 (必須遵守并實(shí)現(xiàn)了協(xié)議的類對(duì)象)
協(xié)議的命名格式:xxxDelegate
所有,以后定義代理時(shí),如下
// 定義了一個(gè)名叫 JuneDelegate 的協(xié)議
@protocol JuneDelegate <NSObject>
@optional
- (void)didSelectItemAtIndex:(NSUInteger)index withView:(JuneView *)juneView ;
@end
@interface JuneView : UIView
@property (nonatomic, weak) id<JuneDelegate> delegate;
@end
@implementation JuneView
- (void)clickItem:(UIButton *)item
{
if ([_delegate respondsToSelector:@selector(didSelectItemAtIndex:withView:)]) {
[_delegate didSelectItemAtIndex:item.tag withView:self ];
}
}
@end
delegate為什么用weak或assign修飾,而不用strong修飾?
在ARC中,只要對(duì)象沒(méi)有強(qiáng)指針就會(huì)自動(dòng)釋放,防止循環(huán)引用。
詳細(xì)解釋