學習block時的一些筆記
1.完整寫法
void(^ blockName)(arg)=void^(arg){};
2.block 可以使用擷取到的自動變數,但是不允許修改重新賦值。
例:
int m=3;
char* str1="str1";
void(^block1)(void)=^(){
NSLog(@"%d,%s",m,str1);
};
m=6;
str1="變化";
block1();
OUTPUT:3,str1
若要修改自動變數的值必須新增__block
block以及擷取自動變數的本質
使用clang -rewrite-objc 命令轉化上面的程式碼
/**
__block_impl 結構體
*/
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
/**
__main_block_impl_0結構體
*/
struct __main_block_impl_0 {
//__block_impl 結構體
struct __block_impl impl;
//__main_block_desc_0 結構體
struct __main_block_desc_0* Desc;
int m;
char *str1;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _m, char *_str1, int flags=0) : m(_m), str1(_str1) {
//_NSConcreteStackBlock 用於初始化__block_impl 結構體的isa成員 表明該block型別為NSConcreteStackBlock
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
/**
1.變換後的block1 被作為簡單的C語言函式來處理
2.函式中的__cself 相當於OC中的self 這裡指代__main_block_impl_0結構體的指標
^(){
int n=m+3;
printf("%d,%s",m,str1);
};
*/
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int m = __cself->m; // bound by copy 自動變數被儲存到Block的結構體例項中。需要注意的是Block中不能直接使用C語言資料型別的自動變數,原因是C語言不允許這種操作
char *str1 = __cself->str1; // bound by copy
int n=m+3;
printf("%d,%s",m,str1);
}
/**
__main_block_desc_0 結構體
*/
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, char * argv[]) {
int m=3;
char* str1="str1";
/*
void(^block1)(void)=^(){
int n=m+3;
printf("%d,%s",m,str1);
};
*/
void(*block1)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, m, str1));
m=6;
str1="變化";
((void (*)(__block_impl *))((__block_impl *)block1)->FuncPtr)((__block_impl *)block1);
}
_ _block 修飾的變數 本質
例:__block int m=3;此時m會被轉化為__Block_byref_m_0結構體
struct __Block_byref_m_0 {
void *__isa;
__Block_byref_m_0 *__forwarding; (指向m:__Block_byref_m_0本身)
int __flags;
int __size;
int m;// m=3
};
__Block_byref_m_0 *__forwarding;//持有指向該例項自身的指標,通過成員變數__forwarding訪問成員變數val
解決迴圈引用問題
__weak typeof(_tom) weak = _tom;
_tom.block = ^{
__strong typeof(weak) strong = weak;
};
__weak : 打破強引用鏈 即_tom物件強引用block物件,block物件強引用_tom物件
__strong:在block中聲明瞭一個區域性變數,暫時“強引用”_tom物件,由於block並不會強引用block內部宣告的__strong修飾的區域性變數。所以這樣即保證了在block呼叫時_tom物件存在又不會造成迴圈引用。