-
object->block->object(对象强引用块,块中捕获对象)
@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.....
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框架下的对象时涉及到的对象方法有:- __bridge: 只做类型转换,不修改相关对象的引用计数,原来的Core Foundation 对象在不用时,需要调用CFRelease 方法.
- __bridge_retained:类型转换后,将相关对象的引用计数加 1,原来的 Core Foundation 对象在不用时,需要调用CFRelease 方法.
- __bridge_transfer:类型转换后,将该对象的引用计数交给ARC管理, Core Foundation 对象在不用时,不再需要调用 CFRelease 方法.
- about block
对应的数据结构如下:
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 时会被销毁.
对于block外的变量引用,block默认是将其复制到其数据结构中来实现访问的
对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的(能够修改值)
在 ARC 开启的情况下,将只会有 NSConcreteGlobalBlock 和 NSConcreteMallocBlock 类型的 block
参考链接:
https://stackoverflow.com/que...
http://blog.parse.com/learn/e...
http://blog.devtang.com/2013/...