暂停/恢复后,iOS UIView变慢

时间:2019-12-05 14:47:12

标签: ios swift uiview uiimage core-graphics

我注意到了一件奇怪的事情:就挂起/恢复后执行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)
  }
}

0 个答案:

没有答案
相关问题