如何编写稳定流畅的iOS移动端应用
原文链接:http://www.jianshu.com/p/f4adce56166f
不忘初心
在过去几年间,移动应用以雷霆之势席卷全球。我们在工作和休闲时间中使用互联网的方式,已经随着移动应用的前进脚步发生了变革。在开发应用的时候,人们也开始考虑“移动优先”的做法。我们正在面对全新一代的移动设备,诸如可穿戴设备或众多移动配件——正是它们构成了“万物互联”的世界。我们将面对全新的用户界面,通过它们数据展示及指令接收处理。同时,我们还将看到,越来越多的公司将真正地践行“移动优先”的思路。而在未来数年中,这一切都将影响我们设计、开发和测试软件的方式。
把一个客户端做得稳定、无奔溃、流畅,是写客户端朋友的梦想,但是,我们面临的结果往往是不如人意的。天下武功,唯快不破。很多公司都信奉这个教条。恨不得把app开发周期压缩到最低,这就导致了开发中隐藏了很多问题。有点经验的工程师草率的优化一下,更糟的情况是那些没有经验的工程师甚至不会对app进行任何优化,这将会使情况变的更糟。
十年前,移动设备的硬件资源是非常有限的.甚至连浮点数都是被禁止的.因为浮点数能导致计算的速度变慢。科技发展如此迅速的今天,硬件很大程度上可以弥补软件的短板。但是硬件的进步终究无法掩饰软件的不足,这也是写这篇文章的初心。
移动端关注要点
在程序开发中,测试是必不可少的。移动端测试按大的类型划分可以分为白盒测试和黑盒测试。
白盒测试一般是由开发人员使用编码的方式进行。测试者需要接触程序的内部代码;而黑盒测试可以在不知道程序内部结构和代码的情况下进行。
下面是主要的测试流程了:
冒烟测试:在软件测试中,冒烟测试是指快速验证APP的主要功能(例如:微信的登陆、退出、发消息等功能) 。如果没有发现问题,再进行更加深入的测试工作;如果发现有问题,就说明APP有重大缺陷。
功能测试:功能测试也叫行为测试,需要根据测试用例来验证应用预期的功能有没有实现。
自由探索式测试:尝试边界条件、输入特殊符号、异常网络环境、突然中断程序等操作 。功能测试的目的是验证正常的功能有没有实现,而自由探索测试的目的就是为了试试应用在极端的操作下会不会出现问题。探索式测试就是要找到能让应用出错的操作。
回归测试:对之前使用我们的服务测试过的应用,将案例复测一遍。
移动端关注的一些指标
运行多少小时不崩溃;
多次打开页面,控制崩溃率;
界面优化,如何才能让用户不急躁、不烦躁;
服务器没有返回数据,是否会导致奔溃;
网络不好,数据来的太慢,界面是否不流畅;
从数据库读的数据太慢如何解决等。
移动端界面应该有自己的逻辑,需要网络数据的地方,应该有默认值,这样在网络数据没有返回的情况下,让用户有数据可以看到。收到的网络数据应该是通过某种方式刷新到界面,而不是等到数据返回才刷新页面。当没有网络数据的时候,界面应该可以自成一体,走的通流程,不强依赖网络数据。
在弱网模式下调试是我们必备的功力,因为我们要考虑用户的实施环境通常都不会很好。把经常使用的数据,存到缓存,提高APP的运行效率、界面流程度。同时,我们需要具备收集奔溃日志的功能,这样才能更好的减少崩溃,提高用户体验。
界面卡顿产生的原因和解决方案
iOS界面处理是在主线程下进行的,系统图形服务通过 CADisplayLink 等机制通知 App,App 主线程开始在 CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。随后 GPU 会把渲染结果提交到帧缓冲区去,等待下一次刷新信号到来时显示到屏幕上。显示器通常以固定频率进行刷新,如果在一个刷新时间内,CPU 或者 GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。这就是界面卡顿的原因。CPU 和 GPU 不论哪个阻碍了显示流程,都会造成掉帧现象。
CPU 造成的资源消耗有以下几种:
- 对象创建
- 对象调整
- 对象销毁
- 布局计算
- Autolayout
- 文本计算
- 文本渲染
- 图片的绘制和解码
GPU 资源消耗有下面几种情况:
- 纹理的渲染
- 视图的混合 (Composing)
- 图形的生成等
具体可以参考这篇文章
用 Instruments 来检验你的app
时间事件查看器-Time Profiler
在xcode的菜单中选择 product->Profile
我们会看到下面的界面:
点击Time Profiler进入。
下面我们来深究如下的控制面板:
以下介绍下配置选项:
- Separate by Thread: 每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的"重"线程。
- Invert Call Tree: 从上倒下跟踪堆栈,这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法.也就是说FuncA{FunB{FunC}} 勾选此项后堆栈以C->B-A 把调用层级最深的C显示在最外面。
- Hide System Libraries: 勾选此项你会显示你app的代码,这是非常有用的. 因为通常你只关心cpu花在自己代码上的时间不是系统上的。
- Flatten Recursion: 递归函数, 每个堆栈跟踪一个条目。
- Top Functions: 一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。因此,如果函数A调用B,那么A的时间报告在A花费的时间加上B.花费的时间,这非常真有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。
找到Detail面板里最耗时的进程,点击进去可以看到代码,观察是否有异,如此便可逐步优化应用的运行效果了。
修改好后,在仪器重新运行该应用程序Product—Profile(或⌘I-记住,这些快捷键真的会为您节省一些时间)。
分配工具
这个时候你会发现两个曲目。一个叫(分配)Allocations,以及一个被称为VM Tracker(虚拟机跟踪)。
内存泄漏有两种泄漏。第一个是真正的内存泄漏,一个对象尚未被释放,但是不再被引用的了。因此,存储器不能被重新使用。第二类泄漏是比较麻烦一些。这就是所谓的“无界内存增长”。这发生在内存继续分配,并永远不会有机会被释放。如果永远这样下去你的程序占用的内存会无限大,当超过一定内存的话 会被系统的看门狗给kill掉。
内存警告是ios处理app最好的方式,尤其是在内存越来越吃紧的时候,你需要清除一些内存。内存一直增长其实也不一定是你的代码出了问题,也有可能是UIKit 系统框架本身导致的。
自己动手观察下,一切自然明了。
内存泄露
这一类泄漏是前面提到的 - 当一个对象不再被引用时出现的那种,检测泄漏可以理解为一个很复杂的事情,但泄漏的工具记得已分配的所有对象,通过定期扫描每个对象以确定是否有任何不能从任何其他对象访问的。
关闭仪器,回到Xcode和选择Product->Profile
点击进入,运行:
自己动手尝试下,找到右边面板里,如果有黑色标识的方法,进入看看。学习就是多尝试。
篇幅有限,更多的内容我们下次再聊。
如何编写稳定流畅的iOS移动端应用的更多相关文章
- DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端
最近头脑里面一直在想怎么样让能让大家基于DIOCP上写出稳定的服务端程序.很多朋友问我,你DIOCP稳定吗,我可以用他来做三层服务器吗? 当时我是这样回答的,我只能保证DIOCP底层通信的稳定. 说实 ...
- html5音频audio对象处理以及ios微信端自动播放和息屏后唤醒的判断---可供参考(功能都完整实现了,只是细节还没处理的很好)
// html模版中的 此处结合了weui样式整合的微信手机端片段代码(不可直接粘贴复制进行使用)里面含有一些php的写法,可直接略过..###重点参考js代码### <div> < ...
- HTC one/M7电信802d 毒蛇ViperOne2.1.0/高级毒蛇工具/完美root,精简/更多自定义,稳定,流畅ROM
ROM版本 HTC One/M7 802d ROM作者 雪狼团队·大盛 http://weibo.com/DaShengdd Android版本 Android 4.2.2 创建日期 2013.09. ...
- ele.me在IOS浏览器端启动APP的技巧分析
ele.me在IOS浏览器端启动APP的技巧分析 巧妙利用后台重定向,在schemes启动时提示用户打开,启动不了APP时能够及时跳转至下载页面. 避免报错页面的出现以及用户还没来的及选择就跳转到下载 ...
- iOS 移动端生成工具开发
代码地址如下:http://www.demodashi.com/demo/11284.html 一.准备工作 编译环境 xcode 用于生成冗余架构代码, 实现生成零耦合架构 二.程序实现 上个月的一 ...
- ios移动端浏览器点击事件失效的解决方案
点击事件失效的原因可能是因为,你用了事件代理了, 比如这样 $(document).on("click",".fd",function(){ }) 这段代码在安 ...
- js时间操作getTime(),ios移动端真机上返回显示NAN
ios移动端,js时间操作getTime(),getFullYear()等返回显示NaN的解决办法及原因 在做移动端时间转化为时间戳时,遇到了一个问题,安卓手机上访问时,能拿到时间戳,从而正确转换时间 ...
- 解决ios移动端双击页面下移
ios移动端在双击弹出层的时候会出现页面下移,露出底层页面的现象 解决办法: <!DOCTYPE html> <html> <head> <meta char ...
- 奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术
奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术
随机推荐
- BZOJ3944 Sum
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- Python Day17
jQuery jQuery是一个兼容多浏览器的javascript库,核心理念是write less,do more(写得更少,做得更多),对javascript进行了封装,是的更加便捷的开发,并且在 ...
- 移动web页面前端开发总结
移动web在当今的发展速度是一日千里,作为移动领域的门外汉,在这段时间的接触后,发现前端开发这一块做一个小小的总结. 1.四大浏览器内核 1.Trident (IE浏览器) :因为在早期IE占有大量的 ...
- Struts2--属性设置方式
Struts2自动获取/设置数据的方式一共分为两种 属性驱动(FieldDriven) 模型驱动(ModelDriven) 属性驱动 属性又分为两种: |- 基本数据类型 |- JavaBean属性类 ...
- iMac 升级到10.12后,蓝牙不能用
解决办法: 断开所有外接USB包括,自带的与Magic Keyboard连接那根线. 再重新启动,就好了. 引用:http://www.jianshu.com/p/87e25a072623
- Apache Shiro 学习记录3
晚上看了教程的第三章....感觉Shiro字符串权限很好用....但是教程举的例子太少了.....而且有些地方讲的不是很清楚....所以我也自己测试了一下....记录一下测试的结果.... (1) * ...
- Xms Xmx PermSize MaxPermSize 区别
Eclipse崩溃,错误提示: MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) s ...
- 360浏览器 默认IE7渲染的解决
<meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1" /> http://st ...
- 简单的 MessageBox
有时候我们只是想实现一个消息框,给用户一些文字提醒,就像javascript的alert那样.没必要因此动用那些庞大的GUI库,下面是几种轻快的实现方法. 1. ctypes import ctype ...
- CentOS 6.5 安装 Redis-3.2.6
到官网下载最新版的 Redis-3.2.6, 我把它放到文件夹:/usr/local/src/centos-sdk/source2/redis 安装脚本 redis-3.2.6.sh #!/bin/b ...