一. autoreleasepool
1.适用场景:创建大量临时对象的时候
2.怎么用
@autoreleasepool{
@ autoreleasepool{
for(){
}
}
}
3.主线程自己有autoreleasepool ,任何自定义线程,必须创建自己的autoreleasepool
二.关键字
1.__strong retain ARC版本,场景: block内部 可以 强引用 self
2.__weak 指针自动置为nil
3.__unsafe_unreatained 与__weak 类似,指针不会置为nil
4.__bridge CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化
CF->OC:
CFStringRef aCFString = CFStringCreateWithCString(NULL, "bridge", kCFStringEncodingASCII);
self.myString = (__bridge NSString *)(aCFString);
CFRelease(aCFString);
OC->CF:
NSString *aString = [NSString stringWithFormat:@"test"];
CFStringRef cString = (__bridge CFStringRef)(aString);
5.CF ->OC __bridge_transfer CFBridgingRelease() 涉及对象所有权转换,OC释放
NSString *aNSString = [[NSString alloc]initWithFormat:@"test"];
CFStringRef aCFString = (__bridge_retained CFStringRef) aNSString;
aNSString = (__bridge_transfer NSString *)aCFString;
aNSString = nil;
6.OC ->CF __bridge_retained:涉及对象所有权转换,CF释放
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRefref=(__bridge_retained CFURLRef)url;
CFRelease(ref);
三. 属性
1.strong 强引用
2.weak 弱引用
3.assign 值类型(Int,bool)
4.copy 修饰block,Mutablexxxx类型的,。外界传Mutablexxxx,直接copy成另一个对象,传入的这个对象改变,不影响被copy出来的这个。
5.unsafe_unretained 类似 _unsafe_unreatained。
四.僵尸对象作用
1.当一个对象被释放之后,又有对象访问它。我们想知道哪些对象访问它,于是可以开启僵尸对象,不让它释放,标记为僵尸对象,所有访问记录都会被记录下来。影响:会导致使用大量内存
2.怎么开启僵尸对象 Product -> Scheme -> Edit Scheme -> Run -> Diagnostics -> Enable Zombie Objects
五. 循环引用
1.两个对象 相互 强引用
-
如何避免 父类对象 强,子对象弱。比如 观察者强,被观察弱。委托:实现委托的强,调用委托的弱
3.双向链表:(暂时不懂???)
六. 什么导致循环引用
1.将self 传入 子对象(前提,self 引用了 子对象)
2.block 内部使用 self,self 又引用block 内部的 某个对象。
3.定时器,当调用
self.timer = [NSTimer scheduledTimerWithTimeInterval:<#(NSTimeInterval)#> repeats:<#(BOOL)#> block:<#^(NSTimer * _Nonnull timer)block#>]
这个时候timer被运行循环强引用(虽然不是显示的),self 强引用,一共两个强引用。只能通过self.timer = nil 去掉self 的强引用,运行循环的强引用 只能通过invalidate 移除引用(不要在dealloc里面调用,想想为什么?)
4.键值观察
官方文档,你需要自行维护他们的强引用。(个人理解: 观察者是控制器,被观察者是个普通对象。当addobserver时,这个时候就已经相互引用了,remove的时候,两者相互引用关系解除)
5.通知中心 思想同上
七. 严格编译模式 strict selector
启用后,当调用[arr objectAtIndex].property,会警告,让你指定数组内元素的类型。
八.什么时候用单例,日志,埋点,缓存
#九. 找到神秘持有者
场景:有时候某个对象明明美没释放,但是instrument就是分析不出来。如何找到这个对象的所有引用?
(1)暂时禁用ARC,在retain方法中 打印出来调用日志。然后分析
#if !__has_feature(objc_arc)
- (instancetype)retain{
NSLog(@"赵先生:%s--%@",__PRETTY_FUNCTION__,[NSThread callStackSymbols]);
return [super retain];
}
#endif
#if !__has_feature(objc_arc)
- (oneway void)release{
[super release];
NSLog(@"赵先生:%s--%@",__PRETTY_FUNCTION__,[NSThread callStackSymbols]);
}
#endif
注意:实测这个方法太麻烦,感觉没什么用
(2)建议:XCode 运行起来 点击 memory debug,左侧出来对象列表,点击任意对象,右侧出现引用图表
(3)instrument 的allocation 可以调试出来,不过你得一个一个看release retain,进行对比
十. 个人总结
(1).避免block使用外部变量
(2)定时器,观察者
(3)NSError 用 __autorelasing 修饰
网友评论