iOS性能优化之页面加载速率

iOS性能优化之页面加载速度git

iOS性能优化之页面加载速率

前言

以前搜罗了网上不少关于iOS性能优化方面的资料 ,本人和个人小伙伴们也用了一些时间针对本身的App进行了App的启动速率、页面的加载速率和 页面的帧率方面进行了优化,因此结合了理论和实践,把咱们在实践中主要踩过的坑和须要注意的东西 ,总结了一下,但愿能够帮到正在准备进行App的性能优化的你。今天主要讲一下App的页面加载速率的优化。github

目的

为了找到真正使咱们的App缓慢的缘由,咱们使用Xcode或者一些第三方平台,进行数据测试;性能优化

1、页面加载速率的定义

页面加载速率:关于页面的加载速度的统计,咱们是测试一个viewcontroller从viewdidload的第一行到viewdidappear的最后一行所用的时间。bash

2、页面加载速率的目标值

目标:页面加载速率最好完美的时间在0.3s左右 为了弄明白,究竟是什么缘由让咱们的App,页面加载速度相对来讲比较慢,咱们对页面的UI进行优化,数据也进行了异步加载,咱们hook数据一看,页面的加载速度果真有所减小,可是减小的值大概只有0.03s,很明显这个值不足以达到咱们想要的效果,后来,经过写了一些测试demo,针对空白页面和有UI建立的页面进行各类对比后,彷佛和咱们页面加载过程当中的push动画有很大的关系;下面所作的实验主要是为了验证这个问题,针对这个问题,我选取了咱们工程的一个类,对有push进入到这个页面有过场动画和没有动画进行测试,如下数据是测试结果: 网络

经过这个实验,咱们能够看出,不加动画的话,咱们的页面加载的速度能够说是没有任何的卡顿,超级迅速,可是若是把过场动画给打开,单是动画的时间就是在0.5s左右,而s咱们是但愿用户在点击跳转页面的时候,目标是页面在0.3s【注:0.3s是根据本身App的状况 ,基于性能优化的2-5-8原则来定义的。(2-5-8原则:就是当用户可以在2秒之内获得响应时,会感受系统的响应很快;当用户在2-5秒之间获得响应时,会感受系统的响应速度还能够;当用户在5-8秒之内获得响应时,会感受系统的响应速度很慢,可是还能够接受;而当用户在超过8秒后仍然没法获得响应时,会感受系统糟透了,或者认为系统已经失去响应,而选择离开)】左右呈现,这若是加动画,这个目标很难达到;不过经过查找相关资料,咱们证明了咱们能够把若是有过场动画的页面,去掉动画,而是经过咱们本身去给用户添加一个过场动画,而这个时间是能够受到咱们本身的控制,而不是傻傻的等动画结束后再加载页面内容。的这就是说,能够一边动画的时候,一边已经开始加载页面相关东西了,这样能够大大的优化页面加载时间。app

3、优化前数据

4、 优化后的数据

到这里 ,你必定想问 :我该如何hook数据的???

5、如何进行数据的收集

  1. 给UIViewController 建立一个分类 eg :UIViewController+Swizzle异步

  2. 代码以下ide

#import <UIKit/UIKit.h>
#import <objc/runtime.h>

@interface UIViewController (Swizzle)
@property(nonatomic,assign) CFAbsoluteTime viewLoadStartTime;

@end

复制代码
#import "UIViewController+Swizzle.h"
#import <objc/runtime.h>

static char *viewLoadStartTimeKey = "viewLoadStartTimeKey";
@implementation UIViewController (Swizzle)
-(void)setViewLoadStartTime:(CFAbsoluteTime)viewLoadStartTime{
objc_setAssociatedObject(self, &viewLoadStartTimeKey, @(viewLoadStartTime), OBJC_ASSOCIATION_COPY);

}
-(CFAbsoluteTime)viewLoadStartTime{
return [objc_getAssociatedObject(self, &viewLoadStartTimeKey) doubleValue];
}
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL origSel = @selector(viewDidAppear:);
SEL swizSel = @selector(swiz_viewDidAppear:);
[UIViewController swizzleMethods:[self class] originalSelector:origSel swizzledSelector:swizSel];

SEL vcWillAppearSel=@selector(viewWillAppear:);
SEL swizWillAppearSel=@selector(swiz_viewWillAppear:);
[UIViewController swizzleMethods:[self class] originalSelector:vcWillAppearSel swizzledSelector:swizWillAppearSel];

SEL vcDidLoadSel=@selector(viewDidLoad);
SEL swizDidLoadSel=@selector(swiz_viewDidLoad);
[UIViewController swizzleMethods:[self class] originalSelector:vcDidLoadSel swizzledSelector:swizDidLoadSel];

SEL vcDidDisappearSel=@selector(viewDidDisappear:);
SEL swizDidDisappearSel=@selector(swiz_viewDidDisappear:);
[UIViewController swizzleMethods:[self class] originalSelector:vcDidDisappearSel swizzledSelector:swizDidDisappearSel];

SEL vcWillDisappearSel=@selector(viewWillDisappear:);
SEL swizWillDisappearSel=@selector(swiz_viewWillDisappear:);
[UIViewController swizzleMethods:[self class] originalSelector:vcWillDisappearSel swizzledSelector:swizWillDisappearSel];
});
}

+ (void)swizzleMethods:(Class)class originalSelector:(SEL)origSel swizzledSelector:(SEL)swizSel
{
Method origMethod = class_getInstanceMethod(class, origSel);
Method swizMethod = class_getInstanceMethod(class, swizSel);

//class_addMethod will fail if original method already exists
BOOL didAddMethod = class_addMethod(class, origSel, method_getImplementation(swizMethod), method_getTypeEncoding(swizMethod));
if (didAddMethod) {
class_replaceMethod(class, swizSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
} else {
//origMethod and swizMethod already exist
method_exchangeImplementations(origMethod, swizMethod);
}
}

- (void)swiz_viewDidAppear:(BOOL)animated
{
[self swiz_viewDidAppear:animated];
if (self.viewLoadStartTime) {
CFAbsoluteTime linkTime = (CACurrentMediaTime() - self.viewLoadStartTime);

NGLog(@" %f s--------------------ssssss %@:速度: %f s",self.viewLoadStartTime, self.class,linkTime  );
self.viewLoadStartTime = 0;
}
}

-(void)swiz_viewWillAppear:(BOOL)animated
{
[self swiz_viewWillAppear:animated];
}

-(void)swiz_viewDidDisappear:(BOOL)animated
{
[self swiz_viewDidDisappear:animated];
}

-(void)swiz_viewWillDisappear:(BOOL)animated
{
[self swiz_viewWillDisappear:animated];
}
-(void)swiz_viewDidLoad
{
self.viewLoadStartTime =CACurrentMediaTime();
NSLog(@" %@swiz_viewDidLoad startTime:%f",self.class, self.viewLoadStartTime );
[self swiz_viewDidLoad];
}

@end
复制代码

##如何进行优化性能

  1. 方法:充分利用push 动画的时间 ,使页面在进入的时候,同事进行相似push 动画,这样能够充分减小页面的加载速度(不包括网络请求时间,网络的请求的时间咱们这边很差控制)。测试

  2. 具体实现代码以下 重写 push方法

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {

if (self.viewControllers.count > 0) {
viewController.hidesBottomBarWhenPushed = YES;
if (animated) {

CATransition *animation = [CATransition animation];
animation.duration = 0.4f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
[self.navigationController.view.layer addAnimation:animation forKey:nil];
[self.view.layer addAnimation:animation forKey:nil];
[super pushViewController:viewController animated:NO];
return;
}
}
[super pushViewController:viewController animated:animated];
}

复制代码
  1. 经过控制台 ,咱们就能够看到页面的加载的速度了,主要的方法是swiz_viewDidLoad 和swiz_viewDidAppear

6、优化后的结果

7、结果分析

咱们能够看出,咱们的页面的viewDidAppear是在过场动画结束后被调用的,而过场动画的持续时间是0.5秒左右。因此咱们的页面平均在0.8秒左右的页面,若是要优化得更好,咱们能够看有没有方法解决这个问题,若是能替换掉动画,让动画在进行的过程当中 ,页面的加载也在异步的进行中,这样 咱们就能够缩短页面的加载时间了;注:但这个加载对加载h5的页面不适用;

一个简单的demo ,因为内容很少 ,因此效果不是太明显 github地址:

github.com/chenHuiMing…

相关文章
相关标签/搜索