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

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

作者: ZhaoXianSheng | 来源:发表于2018-01-24 16:47 被阅读8次

    一. 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 应用开发》阅读笔记(二)核心优化

          本文链接:https://www.haomeiwen.com/subject/ahmraxtx.html