性能优化

作者: 没戏还在演戏 | 来源:发表于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检查渲染
异步渲染

七、网络层

防止多次重复请求

相关文章

  • Android性能优化 - 消除卡顿

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化 - 内存优化 性能分析工具 - Tra...

  • Android性能优化 - 内存优化

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化- 内存优化 性能分析工具 - Trac...

  • 前端性能优化(中)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(上)...

  • 前端性能优化(下)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(中)...

  • Awesome Extra

    性能优化 性能优化模式 常见性能优化策略的总结 Spark 性能优化指南——基础篇 Spark 性能优化指南——高...

  • 常用的后端性能优化六种方式:缓存化+服务化+异步化等

    性能优化专题 前端性能优化 数据库性能优化 jvm和多线程优化 架构层面优化 缓存性能优化 常用的后端性能优化六大...

  • webpack 性能优化

    webpack性能优化 开发环境性能优化 生产环境性能优化 开发环境性能优化 优化打包构建速度 优化调试功能 生产...

  • iOS性能优化 - 整理

    本文主要包含: 性能优化 - 卡顿性能优化 - 耗电优化性能优化 - APP启动优化安装包瘦身 一  性能优化 -...

  • 【React.js 20】React性能优化

    React性能优化 React性能优化主要分三块: React 组件性能优化 属性传递优化针对单组件性能优化,很多...

  • Android性能优化(下)

    Android性能优化 内存泄漏和性能优化方式Android性能优化(上)数据库优化和网络优化Android性能优...

网友评论

    本文标题:性能优化

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