object->block->object(对象强引用块,块中捕获对象)objective-c
@interface TestViewController () @property (copy, nonatomic) void(^testMemeoryLeakBlock)(void); @property (copy, nonatomic) NSString* aStr; @end @implementation TestViewController - (void)viewDidLoad { [super viewDidLoad]; self.aStr = @"test string"; __weak typeof(self) weakSelf = self; self.testMemeoryLeakBlock = ^{ NSLog(@"%@",self.aStr); NSLog(@"%@",_aStr); //block 也会捕获带下划线变量中self, __strong typeof(weakSelf) strongSelf = weakSelf; NSLog(@"%@",strongSelf.aStr); NSLog(@"%@",strongSelf->_aStr); }; } - (void)dealloc{ //重写dealloc方法,观察对象是否被释放. NSLog(@"dealloc method excute!"); }
[NSNotificationCenter defaultCenter]addObserverForName......数据结构
[NSNotificationCenter defaultCenter]addObserverForName...其实严格中没有出现循环引用,只是由于强引用形成对象没法释放. @interface TestViewController () @property (strong, nonatomic) id observer; @end @implementation TestViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //这里使用weakSelf时候,能够不用移除观察者. __weak typeof(self) weakSelf = self; self.observer = [[NSNotificationCenter defaultCenter]addObserverForName:UIKeyboardDidHideNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf doSomeThing]; }]; } - (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter]removeObserver:self.observer]; self.observer = nil; //若是是Strong 同时必须置nil //[NSNotificationCenter defaultCenter]-->Observer --CopyBlock-->Self } - (void)dealloc{ NSLog(@"ViewController Dealloc!"); } - (void)doSomeThing{ }
NSTimer scheduledTimerWithTimeInterval.....app
NSTimer会保留其目标对象;知道定时器失效为止,调用invalidate方法可令timer失效,另外 一次性的timer任务执行完也会失效;反复执行的任务容易出现循环引用,若是其余对象又保留 timer必定会引入循环引用,能够引入块来打破这种保留环. @interface NSTimer (invoke) +(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void(^)())block userInfo:(id)userInfo repeats:(BOOL)yesOrNo; @end @implementation NSTimer (ste_invoke) +(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void(^)())aBlock userInfo:(id)userInfo repeats:(BOOL)yesOrNo { return [ self scheduledTimerWithTimeInterval:ti target:self selector:@selector(ste_timerFireMethod:) userInfo:[aBlock copy ] repeats:yesOrNo ]; } +(void)ste_timerFireMethod:(NSTimer*)timer { void(^block)() = timer.userInfo; if (block) { block(); } } @end //使用的时候;也应该注意块的循环引用
Core Foundation 对象的内存管理
咱们建立的Core Foundation 对象在ARC下由咱们本身管理其生命周期(建立了就要对应有释放),当转换为Foundation框架下的对象时涉及到的对象方法有:框架
对应的数据结构以下:ide
struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(void *dst, void *src); void (*dispose)(void *); }; struct Block_layout { void *isa; int flags; int reserved; void (*invoke)(void *, ...); struct Block_descriptor *descriptor; /* Imported variables. */ };
各个字段解释:
isa 指针,全部对象都有该指针,用于实现对象相关的功能.
flags,用于按 bit 位表示一些 block 的附加信息,本文后面介绍 block copy 的实现代码能够看到对该变量的使用.
reserved,保留变量.
invoke,函数指针,指向具体的 block 实现的函数调用地址.
descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针.
variables,capture 过来的变量,block 可以访问它外部的局部变量,就是由于将这些变量(或变量的地址)复制到告终构体中.函数
在 Objective-C 语言中,一共有 3 种类型的 block:
_NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量.
_NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁.
_NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁.ui
对于block外的变量引用,block默认是将其复制到其数据结构中来实现访问的
对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的(可以修改值)
在 ARC 开启的状况下,将只会有 NSConcreteGlobalBlock 和 NSConcreteMallocBlock 类型的 blockatom
参考连接:
https://stackoverflow.com/que...
http://blog.parse.com/learn/e...
http://blog.devtang.com/2013/...spa