ios - 暂停/恢复后 iOS UIView 变慢
问题描述
UIImage.drawAt
我注意到一件奇怪的事情:UIView在挂起/恢复后的执行速度变慢了两倍。在按 Home 并返回应用程序后,我在 iOS 9-13 上的模拟器和设备上看到 FPS 下降了 2 倍。它在String.drawAt
或填充矩形方面的能力保持不变(这也使我在恢复后重新启动时不太可能犯一些错误)。
谁能解释为什么以及如何修复它?恢复后重新创建视图可以解决问题,但我宁愿使用现有实例。
下面是一个简短的例子。您只需要将一些图像添加到资产中(我的是 112x145 PNG,具有透明度)。如果您的图像太小以至于示例应用程序显示 60 FPS,max
请在最后一个方法中增加参数。
编辑确保将您的图像包含在所有 x1、x2、x3 中,以便加载原始分辨率。否则放大将是最慢的操作,而不是绘图。
// AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder,UIApplicationDelegate
{
var window: UIWindow?
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)->Bool
{
self.window=UIWindow(frame: UIScreen.main.bounds)
window!.makeKeyAndVisible()
let testViewController=TestViewController()
window!.rootViewController=testViewController
Runner._instance.testViewController=testViewController
return true
}
func applicationDidEnterBackground(_ application: UIApplication)
{
Runner._instance.stop()
}
func applicationDidBecomeActive(_ application: UIApplication)
{
Runner._instance.start()
}
func applicationWillTerminate(_ application: UIApplication)
{
Runner._instance.stop()
}
}
class Runner: NSObject
{
static let _instance=Runner()
var testViewController: TestViewController!
var displayLink: CADisplayLink!
var fps=0
var lastFpsCounterTime=Date().timeIntervalSince1970
var fpsCounter=0
func start()
{
if displayLink == nil
{
displayLink=CADisplayLink(target: self,selector: #selector(Runner.run))
displayLink.add(to: RunLoop.main,forMode: RunLoop.Mode.common)
}
}
func stop()
{
displayLink?.invalidate()
displayLink=nil
}
@objc func run()
{
if lastFpsCounterTime+1<Date().timeIntervalSince1970
{
fps=fpsCounter
lastFpsCounterTime=Date().timeIntervalSince1970
fpsCounter=0
}
fpsCounter+=1
testViewController.view.setNeedsDisplay()
}
}
class TestViewController: UIViewController
{
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
loadView()
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
{
super.init(nibName: nibNameOrNil,bundle: nibBundleOrNil)
loadView()
}
override func loadView()
{
view=TestView(frame: UIScreen.main.bounds)
}
}
class TestView: UIView
{
let image=UIImage(named: "card")!
required init?(coder: NSCoder)
{
super.init(coder: coder)
}
override init(frame: CGRect)
{
super.init(frame: frame)
isOpaque=true
}
override func draw(_ _rect: CGRect)
{
let context=UIGraphicsGetCurrentContext()!
context.setFillColor(red: 1, green: 1, blue: 1, alpha: 1)
context.fill(bounds)
let max=50 //Choose max high enough to get less than 60 FPS
let time=Date().timeIntervalSince1970
for i in 1...max
{
//image.draw(at: ) is affected by suspend/resume, but "String".draw(at: ) is not
image.draw(at: CGPoint(x: (image.size.width+bounds.width)*CGFloat(time.truncatingRemainder(dividingBy: Double(1+i))/Double(1+i))-image.size.width,y: bounds.height*CGFloat(i)/CGFloat(max)))
}
let font=UIFont(name: "Arial", size: 15)!
let textFontAttributes=[NSAttributedString.Key.font: font,
NSAttributedString.Key.foregroundColor: UIColor(red: 1, green: 0, blue: 0, alpha: 1),
NSAttributedString.Key.paragraphStyle: NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle]
"FPS: \(Runner._instance.fps)".draw(at: CGPoint(x: 2,y: 30),withAttributes: textFontAttributes)
}
}
解决方案
推荐阅读
- java - 使用 java 中的 JNI 从 c++ 中获取 hashmap 值时出错
- .net - 为什么.NET OData 序列化器这么慢
- android - 使用 dagger 注入使用 WorkManager 处理已注销状态
- python - 为什么 LDAP_MATCHING_RULE_IN_CHAIN 或 1.2.840.113556.1.4.1941 为 AD 用户的递归组提供空白结果?
- sql - 甲骨文。从选择的广告中获取最大值然后进行比较
- mongodb - 使用聚合在嵌套数组中选择文档的字段
- android - 如何使整个活动不响应触摸?
- python - 从python中的n个点找到表示折线所需的最小点
- unity3d - 如何在脚本中访问统一着色器属性?
- kubernetes - 在 Kubernetes 中,如何在服务选择器中按名称选择 pod?