對(duì)象類型的auto變量
-
1.當(dāng)block內(nèi)部訪問了對(duì)象類型的auto變量時(shí)
- 如果block是在棧上,將不會(huì)對(duì)auto變量產(chǎn)生強(qiáng)引用
-
2.如果block被拷貝到堆上
- 會(huì)調(diào)用block內(nèi)部的copy函數(shù)
- copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
- _Block_object_assign函數(shù)會(huì)根據(jù)auto變量的修飾符(__strong、__weak、__unsafe_unretained)做出相應(yīng)的操作,形成強(qiáng)引用(retain)或者弱引用
-
3.如果block從堆上移除
- 會(huì)調(diào)用block內(nèi)部的dispose函數(shù)
- dispose函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_dispose函數(shù)
- _Block_object_dispose函數(shù)會(huì)自動(dòng)釋放引用的auto變量(release)

代碼一 - 運(yùn)行在ARC環(huán)境下 - block被強(qiáng)指針引用,所以在堆上。
#import <Foundation/Foundation.h>
#import "Person.h"
typedef void (^MJBlock)(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
MJBlock block;
{
Person *person1 = [[Person alloc] init];
person1.age = 10;
person1.name = @"person1";
Person *person2 = [[Person alloc] init];
person2.age = 100;
person2.name = @"person2";
Person *person3 = [[Person alloc] init];
person3.age = 1000;
person3.name = @"person3";
__weak Person *weakPerson = person2;
__strong Person *strongPerson = person3;
block = ^{ // 因?yàn)樵揵lock已經(jīng)被強(qiáng)引用,所以此時(shí)在堆上
NSLog(@"---------%d", person1.age);
NSLog(@"---------%d", weakPerson.age);
NSLog(@"---------%d", strongPerson.age);
};
NSLog(@"end");
}
NSLog(@"------");
}
return 0;
}
在不同的地方打斷點(diǎn)調(diào)試運(yùn)行
- 1.在第一個(gè)括號(hào)內(nèi)打斷點(diǎn)

因?yàn)槿齻€(gè)person對(duì)象都還在作用域內(nèi),所以大家都還沒有被釋放
- 在第二個(gè)括號(hào)內(nèi)打斷點(diǎn)

因?yàn)檫@個(gè)時(shí)候已經(jīng)超出三個(gè)person變量的作用域,因?yàn)閣eakPerson被weak修飾,所以這個(gè)時(shí)候被釋放。
- 在第三方括號(hào)內(nèi)打斷點(diǎn)

因?yàn)檫@個(gè)時(shí)候已經(jīng)超出block的作用域,block被釋放,所以被它所引用的的對(duì)象也釋放了
代碼一 - 運(yùn)行在ARC環(huán)境下 - block沒有強(qiáng)指針引用,所以在棧上。
int main(int argc, const char * argv[]) {
@autoreleasepool {
MJBlock block;
{
Person *person1 = [[Person alloc] init];
person1.age = 10;
person1.name = @"person1";
Person *person2 = [[Person alloc] init];
person2.age = 100;
person2.name = @"person2";
Person *person3 = [[Person alloc] init];
person3.age = 1000;
person3.name = @"person3";
__weak Person *weakPerson = person2;
__strong Person *strongPerson = person3;
^{ // 因?yàn)樵揵lock沒有被強(qiáng)引用,所以此時(shí)在棧上
NSLog(@"---------%d", person1.age);
NSLog(@"---------%d", weakPerson.age);
NSLog(@"---------%d", strongPerson.age);
};
NSLog(@"end");
}
NSLog(@"------");
}
return 0;
}
運(yùn)行結(jié)果如下
- 1.在第一個(gè)括號(hào)內(nèi)打斷點(diǎn)

因?yàn)槿齻€(gè)person對(duì)象都還在作用域內(nèi),所以大家都還沒有被釋放
-
2.在第二個(gè)括號(hào)內(nèi)打斷點(diǎn)
image.png
因?yàn)閎lock沒有被強(qiáng)指針引用,在棧上,并且已經(jīng)超出block的作用域,所以block被釋放,被它所引用的對(duì)象也釋放了。
面試代碼一
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
Person *p = [[Person alloc] init];
__weak Person *weakP = p;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"1-------%@", p);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"2-------%@", weakP);
});
});
NSLog(@"touchesBegan:withEvent:");
}
運(yùn)行結(jié)果

1秒后Person被釋放
面試題二
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
Person *p = [[Person alloc] init];
__weak Person *weakP = p;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"1-------%@", weakP);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"2-------%@", p);
});
});
NSLog(@"touchesBegan:withEvent:");
}
運(yùn)行結(jié)果

person 3秒后才被釋放
本文參考借鑒MJ的教程視頻,非常感謝.
項(xiàng)目演示代碼
iOS-block-auto-variable
iOS-block-變量
更多block相關(guān)文章
