1.什么是block?它的本質(zhì)是什么臼氨?
block是一個結(jié)構(gòu)體,可以封裝一部分代碼芭届,block存儲在棧區(qū)間储矩,內(nèi)部截獲的變量存儲在堆區(qū)間。
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
};
isa:指向自身類的指針
flags:按bit位褂乍,表示一些block的附加信息
reserverd:保留變量
invoid:函數(shù)指針持隧,block結(jié)構(gòu)體定義后,實際上生成了一個函數(shù)树叽,該函數(shù)指針指向block塊
descriptor:描述block的信息舆蝴,主要是size的大小,以及copy的函數(shù)指針
2.block的基礎(chǔ)使用
1.在 Objective-C 語言中题诵,一共有 3 種類型的 block:
_NSConcreteGlobalBlock 全局的靜態(tài) block洁仗,不會訪問任何外部變量。
_NSConcreteStackBlock 保存在棧中的 block性锭,當函數(shù)返回時會被銷毀赠潦。
_NSConcreteMallocBlock 保存在堆中的 block,當引用計數(shù)為 0 時會被銷毀草冈。
2.修飾符:copy
copy:該block創(chuàng)建是在椝拢空間的,為什么方法執(zhí)行用copy保存在堆空間
weak修飾:block存儲在椩趵猓空間哩俭,在另外地方調(diào)用block時,已經(jīng)銷毀拳恋,造成野指針
3.block的使用場景
1.傳值
A類定義block凡资,在合適的地方,執(zhí)行block塊谬运,B類在某事件中將值傳出
2.block作為參數(shù)
作為開發(fā)者最熟悉的場景應該是網(wǎng)絡請求隙赁,succes和failed后將值傳出
3.block作為返回值
定義一個函數(shù)垦藏,讓block作為返回值,這樣就可以返回一個代碼塊
#import "Person.h"
@implementation Person
- (void (^)(int))dogs
{
return ^(int sums){
NSLog(@"%d",sums);
};
}
@end
在調(diào)用的時候伞访,傳入值
Person *per = [[Person alloc] init];
per.dogs(10);
4.鏈式編程
在代碼塊里面執(zhí)行某些操作完成一些功能掂骏。返回自己,然后繼續(xù)調(diào)用該函數(shù)厚掷,返回一個block弟灼,這樣就可以實現(xiàn)masonry的鏈式調(diào)用效果
masnory
[View mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(anotherView);
make.left.equalTo(anotherView);
make.width.mas_equalTo(@60);
make.height.mas_equalTo(@60);
}];
eg:定義一個計算類,聲明方法
- (Caculater * (^)(int))add
{
__weak Caculater *weakSelf = self;
return ^(int value){
weakSelf.result = weakSelf.result + value;
return weakSelf;
};
}
執(zhí)行計算
Caculater *mgr = [[Caculater alloc] init];
mgr.result = 0;
mgr.add(5).add(6);
NSLog(@"%d", mgr.result);
結(jié)果輸出
2018-07-09 15:31:50.962559+0800 BlcokReview[1855:189577] 11
5.函數(shù)式編程
定義計算類蝗肪,聲明方法
- (instancetype)addBlock:(int (^)(int))blcokName
{
_result = blcokName(_result);
return self;
}
- (instancetype)deteBlock:(int (^)(int))blcokName
{
_result = blcokName(_result);
return self;
}
執(zhí)行計算
Caculater *mgr = [[Caculater alloc] init];
[[mgr addBlock:^int(int value) {
value += 5;
NSLog(@"%d", value);
return value;
}]deteBlock:^int(int value) {
value -= 3;
NSLog(@"%d", value);
return value;
}];
結(jié)果輸出
2018-07-09 17:24:38.402167+0800 BlcokReview[2181:281962] 16
2018-07-09 17:24:38.402321+0800 BlcokReview[2181:281962] 13
4.block使用遇到的問題
1.循環(huán)引用
當一個對象持有了block后袜爪,block內(nèi)部又使用了這個對象或者對象的實例變量、實例方法薛闪,這樣會使block也持有這個對象,這樣相互持有就是循環(huán)引用俺陋,從而導致對象無法釋放引起內(nèi)存泄露豁延。
解決:
要解決循環(huán)引用只需要不要相互持有就行了,也就是說只需要一方持有就可以不讓block再持有當前這個對象就OK腊状。