- 不要等到明天,明天太遙遠(yuǎn),今天就行動(dòng)。
須讀:看完該文章你能做什么?
1.了解block的底層原理
2.什么是____strong__
什么是____weak__
3.什么時(shí)候使用__block
學(xué)習(xí)前:你必須會(huì)什么?(在這里我已經(jīng)默認(rèn)你具備C語(yǔ)言的基礎(chǔ)了)
1.block的使用
一、本章筆記
一、
1.block中可以訪問(wèn)外面的變量
2.block中可以定義和外界同名的變量, 并且如果在block定義了和外界同名的變量,在block中訪問(wèn)的是block中的變量
3.默認(rèn)情況下,不可以在block中修改外界變量的值
4.不默認(rèn)情況下,加上__block 修飾符 可以在block中修改外界變量的值
二、
1.驗(yàn)證為什么不加 __block 不能在block中修改外界變量的值
2.驗(yàn)證而加了 __block 就可以在block中修改外界變量的值
>步驟
1.通過(guò)Clang指令來(lái)獲取系統(tǒng)編譯的C++代碼
2.1.cd到指定文件路徑 ,然后通過(guò)cc -rewrite-objc main.m
3.獲取.cpp文件.跳到最后的104800行左右找到main.m函數(shù)
找到對(duì)應(yīng)的代碼 進(jìn)行對(duì)比(一個(gè)是值傳遞,一個(gè)是地址傳遞)
三、
block是存儲(chǔ)在堆中(copy情況下) 還是棧中(默認(rèn)情況下)
如果在block 中訪問(wèn)了外界的對(duì)象,一定要給對(duì)象加上 __block, 只要加上了 __block 哪怕block在堆中,也不會(huì)對(duì)外界的兌現(xiàn)進(jìn)行retain操作
二、code
main.m
#pragma mark 15-Block注意事項(xiàng)
#pragma mark 概念
#pragma mark - 代碼
#import <Foundation/Foundation.h>
#pragma mark 類
#import "Person.h"
#pragma mark - main函數(shù)
int main(int argc, const char * argv[])
{
#pragma 1.block中可以訪問(wèn)外面的變量
/*
int a = 10;
void (^myBlock)() = ^{
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 2.block中可以定義和外界同名的變量, 并且如果在block定義了和外界同名的變量,在block中訪問(wèn)的是block中的變量
/*
int a = 10;
void (^myBlock)() = ^{
int a = 20;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 3.默認(rèn)情況下,不可以在block中修改外界變量的值
// 因?yàn)閎lock中的變量 和外界的變量 并不是同一個(gè)變量
// 如果block中 訪問(wèn)到了外界的變量,block會(huì)將外界的變量拷貝一份到 堆 內(nèi)存中
// 因?yàn)?block中 使用外界變量是copy, 所以在調(diào)用之前修改外界變量的值,不會(huì)影響到block中copy的值
/*
int a = 10;
NSLog(@"%p",&a); // 0x7fff5fbff7bc
void (^myBlock)() = ^{
// a = 20; // varable is assginable(missing __block type specifier)
NSLog(@"a = %i",a); // 10
NSLog(@"%p",&a); // 0x103000160
};
a = 20;
myBlock();
*/
#pragma 4.不默認(rèn)情況下,不可以在block中修改外界變量的值
// 如果想在block中修改外界變量的值,必須在外界變量 前面加上 __block
// 如果在block中修改了外界變量的值, 會(huì)影響到外界變量的值
/*
__block int a = 10;
NSLog(@"%p",&a);
void (^myBlock)() = ^{
a = 33;
NSLog(@"a = %i",a);
NSLog(@"%p",&a);
};
myBlock();
NSLog(@"a = %i",a);
*/
#pragma 5.為什么不加 __block 不能在block中修改外界變量的值
//
/*
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int a;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_c2811e_mi_0,a);
}
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, const char * argv[])
{
int a = 10; 如果沒(méi)有添加 __block是值傳遞
void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a));
(myBlock)->FuncPtr)(myBlock);
return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
// __main_block_impl_0 應(yīng)該是一個(gè)結(jié)構(gòu)體
// void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)) 其中a 是一個(gè)值傳遞
*/
#pragma code
/*
int a = 10;
void (^myBlock)() = ^{
// a = 10;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 6.為什么加 __block 就可在block中修改外界變量的值
/*
a = 10; 如果 加上 __block之后就是地址傳遞,就可在block中修改外界變量的值
void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
*/
/*
__block int a = 10;
void (^myBlock)() = ^{
a = 13;
NSLog(@"a2 = %i",a);
};
NSLog(@"a1 = %i",a);
myBlock();
NSLog(@"a3 = %i",a);
*/
#pragma 7.面試 -- block是存儲(chǔ)在堆中(copy情況下) 還是棧中(默認(rèn)情況下)
// 默認(rèn)情況下 block存儲(chǔ)在棧中,如果對(duì)block進(jìn)行copy操作,block會(huì)轉(zhuǎn)移到堆中
// 如果block在堆中, block訪問(wèn)了外界的對(duì)象,那么會(huì)對(duì)外界的對(duì)象進(jìn)行retain
// 如果在block 中訪問(wèn)了外界的對(duì)象,一定要給對(duì)象加上 __block, 只要加上了 __block 哪怕block在堆中,也不會(huì)對(duì)外界的兌現(xiàn)進(jìn)行retain操作
// Person *p = [[Person alloc]init];
__block Person *p = [[Person alloc]init];
NSLog(@"retainCount = %lu",[p retainCount]);
void (^myBlock)() = ^{
NSLog(@"p = %@",p);
NSLog(@"retainCount = %lu",[p retainCount]);
};
Block_copy(myBlock);
myBlock();
[p release];
return 0;
}
Person
>>>.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
>>>.m
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"%s",__func__);
[super dealloc];
}
@end
一、獲取cpp文件
image.png
通過(guò)-rewrite-objc指令
image.png
image.png
轉(zhuǎn)成cpp文件
image.png
cpp文件代碼
image.png
image.png