如何优化iOS系统上的图文评论UI界面

简介: 在我们的社交 APP 上,⽤户的动态由精美的照⽚ 、视频和⽂字组成。对于每张照⽚和视频, 我 们都会展示出完整的标题和五个最新评论。由于⽤户喜欢使⽤标题来讲述照⽚背后的故事, 因此它们通常很⻓ 、很复杂, 并且可能包含超链 接和表情符号。渲染如此复杂的⽂本带来了⼀些问题, 它在滚动时造成性能下降。 即使在 iPhone 12 这样的新设备上, 复杂标题的初始⽂本绘制需要⻓达 50 毫秒, ⽽⽂本展示 需要⻓达 30 毫秒, 渲染速度很慢。⽂本问题还是简单问题, 有时我们需要加载更加复杂的图⽚甚⾄视频。所有这些步骤都发⽣在 UI 线程上, 导致app在⽤户滚动时丢帧。

在我的社交 APP 上,⽤户动态由精美的照视频成。于每视频, 我 展示出完整的标题和五最新评论由于⽤户使⽤标题来讲述照背后的故事,因此它们通常很、很复杂且可能包含超接和表情符渲染如此复杂带来问题滚动时造成性能下降。 

即使在iPhone12这样的新设备上,复杂标题的初始制需要⻓达50毫秒,⽽⽂本展示需要⻓达30毫秒,渲染速度很慢。问题还简单问题 需要加更加复杂图⽚⾄视频所有些步发⽣UI 线程上, app⽤户滚动时丢帧

基础知识:

始之前, 最好先了解本的基本念。

线程不应该⽤于繁重的操作,主要于:

1.接受⽤户输⼊/交互;

2.更新UI

线程必须处理太多操作最常的后果是出现丢帧现象,不能保60 fps(每16.67毫秒会发⽣这种现象。

精准地识别并调试丢帧问题

很容易发现帧问题最常的表形式是⽆响应/

可以使友盟+U-APMiPhone12这样的新款设备上是否会发⽣

1.jpg

显⽽iPhone12 上也发⽣了卡, 由此推的代存在化空⽽并⾮⽤户设备 配置问题。接下, 我需要更准确的跟踪卡顿问题。我们尝试了使CADisplayLink    TimeProfiler

使CADisplayLink

class DroppingFramesHelper: NSObject {

private var firstTime: TimeInterval =0.0

private var lastTime: TimeInterval = 0.0

func activate() {

let link = CADisplayLink(target: self, selector: #selector(updat

link.add(to: .main, forMode: .commonModes)

}

@objc private func update(link: CADisplayLink) {

if lastTime ==0{

firstTime = link.timestamp

lastTime = link.timestamp

}

let currentTime = link.timestamp

let elapsedTime = floor((currentTime - lastTime) * 10_000)/10

let totalElapsedTime = currentTime - firstTime

if elapsedTime > 16.7 {

print("[DFH] Frame was dropped with elpased time of \(elapse

}

lastTime = link.timestamp

}

}


然后, 在 AppDelegate 法中访问它⼀个实例:

didFinishLaunchingWithOptionsDroppingFramesHelper().activate()

在,如果测试程序出现丢帧的情可以在控制台上它们

2.jpg

采取的措施

在通控制台和友盟+U-APM知道了掉的情存在,能做些什呢?可以采取些下⾯这些措施:

1视图和透明视图

2连续调⽤中的负载

3JPEG

4渲染

 们将会⼀⼀进⾏讨论

1.减少试图和透明试图的数量

了提⾼应⽤程序的性能,先要做的事是:

 视图

 降低透明度

法很简单

label.layer.opacity = 1.0

label.backgroundColor = .white

了更加容易地察到重的透明度,可以使⼀个⾮便的具:  调试->视图调试->渲染->颜⾊混合

这个⼯可以松地发现视图, 如下所示:

3.jpg

在我不需要这⾥使⽤标签将背景颜⾊设晰。

2.最小化“连续调用函数”中的负载

显⽽cellForItemAtindexPathscrollViewDidScroll这样连续调⽤的函须运算得常快。

所以我们尽可能使单纯视图/元格,使⽤⾮巧快速的法。(例如, 不涉及布局束、象分配的配置)

3.解码JPEG图像

们处丢帧问题时化点像解

通常, 这个操作是在主线程上是由 imageViews 完成的, 但在会导致我应⽤程序慢。

这个问题⼀种决⽅案是码⼯作移后台列。这样操作不UIImageView的正常解样⾼效,mainThread是空的。

 在后台解码图像:

extension UIImage {

class func decodedImage(_ image: UIImage) -> UIImage? {

guard let newImage = image.cgImage else { return nil }


 // To optimize this, you cansomecachecontrol.

let colorspace = CGColorSpaceCreateDeviceRGB()

let context = CGContext(data: nil,

width: newImage.width,

height: newImage.height,

bitsPerComponent: 8,

bytesPerRow: newImage.width * 4,

space: colorspace,

bitmapInfo: CGImageAlphaInfo.noneSkipFir

context?.draw(newImage, in: CGRect(x: 0, y: 0, width: newImage.w

let drawnImage = context?.makeImage()

if let drawnImage = drawnImage {

return UIImage(cgImage: drawnImage)

}

return nil

}

}

可以添加进⼀步的存控制以提效率:


import UIKit

class AsyncImageView: UIView {

private var _image:UIImage?

var image: UIImage? {

get {

return _image

}

set {

_image = newValue

layer.contents = nil

guard let image = newValue else { return }

DispatchQueue.global(qos: .userInitiated).async {

DispatchQueue.main.sync { }

let decodedImage = UIImage.decodedImage(image)

DispatchQueue.main.async {

self.layer.contents = decodedImage?.cgImage

}

}

}

}

可以使“AsyncImageView”,在后台线不是主线程中解码图像。

为什么使用DispatchQueue.main.sync{}?

debug的前期我们尝试不使sync但是程序发⽣了崩溃⾏为了找出原因,使友盟+U-APM检测进⾏测试

4.jpg

可以从图中看出,码导致了OOM警,是由于存警告是在主线程上理的,   正在后台像,所以如果我使太多存, 就意外⾏为并带来极⼤⻛险(例发⽣的崩

4.离屏渲染

们处UI元素的特定可能遇到些离渲染问题需要在呈现它们前准渲染些元素。意味着量使CPUGPU

如何发现这种问题?

使具:  Debug->ViewDebugging->Rendering->ColorOscreen-RenderedYellow和前点的例相似, 使具, 我可以发现⻩⾊红⾊突出示的元素。

以下代码内容:

imageView.layer.cornerRadius = avatarImageHeight / 2.0

使  UIBezierPath代替,可以简单地解特定的离渲染问题

extension UIImage {

class func circularImage(from image:UIImage,size:CGSize)

let scale = UIScreen.main.scale

let circleRect = CGRect(x: 0, y: 0, width: size.width *

 

UIGraphicsBeginImageContextWithOptions(circleRect.size,

 

-> UIImage? {

 

scale, height:

 

false, scale)

let circlePath = UIBezierPath(roundedRect:circleRect,cornerRadius:c

circlePath.addClip()

 

image.draw(in: circleRect)

 

if let roundImage =UIGraphicsGetImageFromCurrentImageContext(){

return roundImage

}

 

return nil

}

}


简而言之,以下是通过调试得出的几点经验:

1.避免CornerRadius属性:

2.避免使ShouldRasterize

3.使  .rounded()更容易算。

4.Shadows会导致离渲染。

其他经验:

可以尝试⼀下以下的化建

1.boudingRectWithSize但是debug程可能常繁重。⾮⾮常需要,请尽量避免使⽤它们

2.检查结构布局, 尤其是使⽤⾃动布局且必须⽀旧设备时

3. 尝试将⼯作放后台列, 但注意存警告。



作者:郑文韬

相关文章
|
2月前
|
搜索推荐 Android开发 iOS开发
探索安卓与iOS系统的用户界面设计哲学
现代移动操作系统的设计哲学不仅仅是技术的表现,更是用户体验与功能实现的结合。本文将深入分析安卓与iOS两大主流系统在用户界面设计方面的差异与共通之处,探讨它们背后的思维模式及其对用户体验的影响。 【7月更文挑战第11天】
|
3天前
|
开发工具 Swift 数据安全/隐私保护
移动应用开发之旅:从零到一的iOS系统探索
【9月更文挑战第16天】在数字时代的浪潮中,移动应用成为连接用户与数字世界的桥梁。本文将带你走进iOS移动操作系统的世界,了解其架构、设计理念以及开发环境。我们将通过Swift语言的简单示例,展示如何构建一个基本的iOS应用,并探讨移动应用开发的未来趋势。无论你是编程新手还是资深开发者,这篇文章都将为你提供宝贵的见解和知识。
|
1月前
|
存储 安全 编译器
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
|
1月前
|
人工智能 自然语言处理 云计算
iOS迎来AI升级:揭秘Apple全新“智能”系统
iOS迎来AI升级:揭秘Apple全新“智能”系统
iOS迎来AI升级:揭秘Apple全新“智能”系统
|
27天前
|
存储 分布式计算 供应链
Spark在供应链核算中应用问题之通过Spark UI进行任务优化如何解决
Spark在供应链核算中应用问题之通过Spark UI进行任务优化如何解决
|
1月前
|
搜索推荐 数据库
最新UI六零导航系统源码 | 多模版全开源
使用PHP+MySql,增加后台管理 多模板选择,支持在后台切换模板 增加常用搜索引擎,如:知乎、哔哩哔哩、在线翻译等(支持自定义) 支持用户提交收录申请,地址:http://域名/apply 部分模板优化和增加部分功能,如返回顶部、获取输入框焦点、时间日期显示等
50 1
|
1月前
|
iOS开发 开发者
iOS 16 系统键盘修复问题之汇编层面模拟两次返回操作的实现如何解决
iOS 16 系统键盘修复问题之汇编层面模拟两次返回操作的实现如何解决
|
1月前
|
存储 iOS开发
iOS 16 系统键盘修复问题之确定UIKeyboardTaskQueue类对_lock的加锁和解锁操作如何解决
iOS 16 系统键盘修复问题之确定UIKeyboardTaskQueue类对_lock的加锁和解锁操作如何解决
|
20天前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
33 0
|
20天前
|
测试技术 Swift iOS开发
探索iOS自动化测试:使用Swift编写UI测试
【8月更文挑战第31天】在软件开发的海洋中,自动化测试是保证船只不偏离航线的灯塔。本文将带领读者启航,深入探索iOS应用的自动化UI测试。我们将通过Swift语言,点亮代码的灯塔,照亮测试的道路。文章不仅会展示如何搭建测试环境,还会提供实用的代码示例,让理论知识在实践中生根发芽。无论你是新手还是有经验的开发者,这篇文章都将是你技能提升之旅的宝贵指南。