性能优化

作者: 没戏还在演戏 | 来源:发表于2020-01-10 14:38 被阅读0次

    一、循环引用

    1.第一种方式 weak+strong(最常用)

    - (void)one{
        __weak typeof(self) weakSelf = self;
        self.block = ^{
            __strong typeof(self) strongSelf = weakSelf;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"%@",strongSelf.name); // self - nil name - nil
            });
        };
        
        self.block();
    }
    

    2.第二种方式__block

    - (void)two{
        __block ViewController *vc = self; // vc 结构体
        self.block = ^{
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"%@",vc.name); // self - nil name - nil
                vc = nil;
            });
        };
        self.block();
    }
    

    3.第三种方式 传参(效率最高)

    self.blockVc = ^(ViewController *vc){
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"%@",vc.name); // self - nil name - nil
            });
        };
        self.blockVc(self);
    

    二、强引用

    - (void)initTimer {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self.target selector:@selector(timerSel) userInfo:nil repeats:YES];
    }
    - (void)timerSel{
        num++;
        NSLog(@"num----> %d",num);
    }
    

    因为runloop -> timer -> target -> self 造成了强引用
    1.简陋的解决

    -(void)viewWillDisappear:(BOOL)animated {
        [self.timer invalidate];
        self.timer = nil;
    }
    

    2.好一点的方式,但是不够灵活

    -(void)didMoveToParentViewController:(UIViewController *)parent{
        if (parent == nil) {
            [self.timer invalidate];
            self.timer = nil;
        }
        NSLog(@"结束");
    }
    

    3.中间层
    定义一个中间层

    @interface YHTimerWapper : NSObject
    - (instancetype)yh_initWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
    - (void)yh_invalidate;
    @end
    
    @interface YHTimerWapper()
    @property (nonatomic, weak) id target;
    @property (nonatomic, assign) SEL aSelector;
    @property (nonatomic, strong) NSTimer *timer;
    @end
    @implementation YHTimerWapper
    - (instancetype)yh_initWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo{
        if (self == [super init]) {
            self.target     = aTarget;
            self.aSelector  = aSelector;
            self.timer      = [NSTimer scheduledTimerWithTimeInterval:ti target:self selector:@selector(timerSel) userInfo:userInfo repeats:yesOrNo];
        }
        return self;
    }
    - (void)timerSel{
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        // 让编译器出栈,恢复状态,继续编译后续的代码!
        if ([self.target respondsToSelector:self.aSelector]) {
            [self.target performSelector:self.aSelector];
        }
    #pragma clang diagnostic pop
    }
    - (void)yh_invalidate{
        [self.timer invalidate];
        self.timer = nil;
    }
    

    使用

    - (void)viewDidLoad {
        [super viewDidLoad];
        //中间层(RACKVOWapper)
        // self -> timerWapper(在self的dealloc方法断开) <-> timer <- runloop
        self.timerWapper = [[YHTimerWapper alloc] yh_initWithTimeInterval:1 target:self selector:@selector(timerSel) userInfo:nil repeats:YES];
    }
    - (void)dealloc{
        [self.timerWapper lg_invalidate];
    }
    

    4.使用block

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"num ");
    }];
    - (void)dealloc{
        [self.timer invalidate];
        self.timer = nil;
    }
    
    1. NSProxy
      是跟NSObject同级的类,加载迅速,消息转发形式更加清晰
    @interface YHProxy : NSProxy
    + (instancetype)proxyWithTransformObject:(id)object;
    @end
    
    @interface YHProxy()
    @property (nonatomic, weak) id object;
    @end
    @implementation YHProxy
    + (instancetype)proxyWithTransformObject:(id)object{
        YHProxy *proxy = [YHProxy alloc];
        proxy.object = object;
        return proxy;
    }
    // sel - imp -
    // 消息转发 self.object
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
        return [self.object methodSignatureForSelector:sel];
    }
    - (void)forwardInvocation:(NSInvocation *)invocation{
        if (self.object) {
            [invocation invokeWithTarget:self.object];
        }
    }
    @end
    

    使用

    self.proxy = [YHProxy proxyWithTransformObject:self];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self.proxy selector:@selector(timerSel) userInfo:nil repeats:YES];
    

    三、内存泄漏检查方式

    1、静态分析Analyze
    2、instrument
    3、MLeaksFinder(更方便)
    4、dealloc

    四、启动时间

    1. 启动分为2种: 冷启动和热启动
    2. 启动的时间分为两部分:main函数执行之前、main函数⾄应用启动完成
      启动优化建议
      main函数之前
      减少动态库、合并一些动态库
      减少Objc类、分类的数量、减少Selector数量
      main函数⾄应用启动完成
      耗时操作,不要放在finishLaunching方法中

    动态库对启动时间的影响测试
    iOS Dynamic Framework 对App启动时间影响实测

    五、应用瘦身

    LinkMap查看文件大小
    LSUnusedResources 查看未使用的文件

    六、渲染

    YYFpsLabel检查渲染
    异步渲染

    七、网络层

    防止多次重复请求

    相关文章

      网友评论

        本文标题:性能优化

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