iOS UIView在挂起/恢复后变慢

iOS UIView在挂起/恢复后变慢,ios,swift,uiview,uiimage,core-graphics,Ios,Swift,Uiview,Uiimage,Core Graphics,我注意到一件奇怪的事情:在挂起/恢复后,UIView在执行UIImage.drawAt方面的速度慢了两倍。在按下Home键并返回应用程序后,我在iOS 9-13的模拟器和设备上看到FPS下降了2倍。它在String.drawAt或填充矩形方面的能力保持不变(在恢复后重新启动时,它也不太可能犯我的错误) 有人能解释为什么以及如何修复它吗?恢复后重新创建视图修复了问题,但我宁愿使用现有实例 下面是一个简短的例子。您只需要将一些图像添加到资源中(我的是112x145 PNG,具有透明度)。如果您的图像

我注意到一件奇怪的事情:在挂起/恢复后,UIView在执行
UIImage.drawAt
方面的速度慢了两倍。在按下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)
  }
}
//AppDelegate.swift
导入UIKit
@UIApplicationMain
类AppDelegate:UIResponder、UIApplicationLegate
{
变量窗口:UIWindow?
func应用程序(application:UIApplication,didFinishLaunchingWithOptions launchOptions:[UIApplication.launchOptions键:任意]?)->Bool
{
self.window=UIWindow(框架:UIScreen.main.bounds)
window!.makeKeyAndVisible()
设testViewController=testViewController()
window!.rootViewController=testViewController
Runner.\u instance.testViewController=testViewController
返回真值
}
func应用程序标识符背景(u应用程序:UIApplication)
{
Runner.\u实例.停止()
}
func applicationIDBecomeActive(u应用程序:UIApplication)
{
Runner.\u instance.start()
}
func应用程序将终止(application:UIApplication)
{
Runner.\u实例.停止()
}
}
类运行程序:NSObject
{
静态let_instance=Runner()
var testViewController:testViewController!
var displayLink:CADisplayLink!
var fps=0
var lastfspcountertime=Date().timeIntervalSince1970
变量计数器=0
func start()
{
如果displayLink==nil
{
displayLink=CADisplayLink(目标:self,选择器:#选择器(Runner.run))
添加(到:RunLoop.main,forMode:RunLoop.Mode.common)
}
}
函数停止()
{
displayLink?.invalidate()
displayLink=nil
}
@objc func run()
{

如果lastFpsCounterTime+1
NSAttributedString.Key.paragraphStyle:NSMutableParagraphStyle.default.mutableCopy()作为!NSMutableParagraphStyle
非常奇怪。测量速度的方法是仪器。
NSAttributedString.Key.paragraphStyle:NSMutableParagraphStyle.default.mutableCopy()as!NSMutableParagraphStyle
非常奇怪。测量速度的方法是仪器。