《高性能 iOS 应用开发》阅读笔记(二)核心优化

一. 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.两个对象 相互 强引用

  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 修饰

你可能感兴趣的:(《高性能 iOS 应用开发》阅读笔记(二)核心优化)