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

在我们的社交 APP 上,?户的动态由精美的照? 、视频和?字组成。对于每张照?和视频, 我们都会展示出完整的标题和五个最新评论。
由于?户喜欢使?标题来讲述照?背后的故事,因此它们通常很? 、很复杂,并且可能包含超链接和表情符号。
渲染如此复杂的?本带来了?些问题,它在滚动时造成性能下降。
即使在 iPhone 12 这样的新设备上,复杂标题的初始?本绘制需要?达 50 毫秒,??本展示需要?达 30 毫秒,渲染速度很慢。
?本问题还是简单问题,有时我们需要加载更加复杂的图?甚?视频。
所有这些步骤都发?在 UI 线程上,导致app在?户滚动时丢帧。
当主线程必须处理太多操作时,最常?的后果是出现丢帧现象,当我们不能保证 60 fps (每 16.67 毫秒? 帧) 时就会发?这种现象。
基础知识 在开始之前,最好先了解本?的基本概念。
主线程不应该?于繁重的操作,?主要?于:
1、接受?户输?/交互;
2、显示结果并更新 UI。
精准地识别并调试丢帧问题 有时我们很容易发现掉帧问题,因为掉帧最常?的表现形式是?响应/卡顿。
我们可以使?友盟+ U-APM检查在 iPhone12 这样的新款设备上是否会发?卡顿。
如何优化iOS系统上的图文评论UI界面
文章图片

显?易?在 iPhone12 上也发?了卡顿,由此推断我们的代码存在优化空间,?并??户的设备 配置问题。
接下来,我们需要更准确的?法来跟踪卡顿问题。
我们尝试了使? CADisplayLinkTimePro?ler
使? 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 的?法中访问它的?个实例:
didFinishLaunchingWithOptions:DroppingFramesHelper().activate()

现在,如果测试程序出现丢帧的情况,我们可以在控制台上监控它们:
如何优化iOS系统上的图文评论UI界面
文章图片

采取措施 现在通过控制台和友盟+ U-APM知道了掉帧的情况存在,我们能做些什么呢?可以采取?些下?这些措施:
(1) 减少视图和透明视图的数量
(2) 最?化“连续调?函数”中的负载
(3) 解码 JPEG 图像
(4) 离屏渲染
我们将会??进?讨论。
1、减少视图和透明视图的数量
为了提?应?程序的性能, ?先要做的事是:
? 减少视图的数量。
? 降低透明度。
解决的?法很简单:
label.layer.opacity = 1.0 label.backgroundColor = .white

为了更加容易地观察到重叠的透明度,我们可以使? ?个?常?便的?具:调试 -> 视图调试 - > 渲染 ->颜?混合层。
这个?具让我们可以轻松地发现重叠的视图, 如下图所示:
如何优化iOS系统上的图文评论UI界面
文章图片

在我们不需要时, 这?使?标签将背景颜?设置为不清晰。
2、最?化“连续调?函数”中的负载
显?易?,像 cellForItemAt indexPathscrollViewDidScroll 这样被连续调?的函数必须运算得?常快。
所以我们尽可能使?最“单纯”的视图/单元格,并使??常轻巧快速的运算?法。(例如,不涉及布局约束、对象分配的配置)
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 can some cache control. 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”, 在后台线程?不是主线程中解码图像。
如何优化iOS系统上的图文评论UI界面
文章图片

debug 的前期我们尝试不使? sync,但是程序发?了崩溃?为。为了找出原因,我们使?了 友盟+ U-APM 的异常检测进?测试。
如何优化iOS系统上的图文评论UI界面
文章图片

可以从图中看出,代码导致了OOM 内存异常报警,这是由于内存警告是在主线程上处理的,?我们正在后台处理图像,所以如果我们使?太多内存, 就会出现意外?为并带来极??险 (例如图中发?的崩溃)
4、离屏渲染
当我们处理 UI 元素的特定属性时, 可能会遇到?些离屏渲染问题, 因为我们需要在呈现它们之 前准备渲染这些元素。这意味着?量使? CPU 和 GPU。
如何发现了这个问题? 我们使?了?具: Debug -> View Debugging -> Rendering -> Color O?screen-Rendered Yellow。
和前?第?点的例?相似, 使?此?具, 我们可以发现以??或红?突出显示的元素。
以下代码内容:
imageView.layer.cornerRadius = avatarImageHeight / 2.0

我们使? UIBezierPath 代替, 它可以简单地解决特定的离屏渲染问题:
如何优化iOS系统上的图文评论UI界面
文章图片

简??之, 以下是通过调试得出的?点经验:
1、避免 CornerRadius 属性;
2、避免使? ShouldRasterize;
3、使? .rounded() 值, 因为更容易计算。
4、Shadows 也会导致离屏渲染
其他建议
读者还可以尝试?下以下的优化建议:
【如何优化iOS系统上的图文评论UI界面】1、?本测量 (boudingRectWithSize),但是 debug 过程可能?常繁重。除??常需要,否则请尽量避免使?它们。
2、检查结构布局,尤其是使??动布局并且必须?持旧设备时。
3、尝试将?作放?后台队列,但请注意内存警告。

    推荐阅读