前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FPS 与 CADisplayLink

FPS 与 CADisplayLink

作者头像
大话swift
修改2019-07-04 17:56:42
1.1K0
修改2019-07-04 17:56:42
举报
文章被收录于专栏:大话swift

iOS系统已顺滑不卡顿闻名,作为开发者我们来看怎么检测你的App的FPS的。众所周知的是NSTimer是定时计数的霸主,然鹅Timer是不准确的。纳尼?哈哈不用紧张,这个不准确是相对来说的,在这个多一秒不多,少一秒不少的世界你还是用Timer吧

我们先来看看官方文档怎么描述CADisplayLink:

A timer object that allows your application to synchronize its drawing to the refresh rate of the display.

我们来看个例子:

代码语言:javascript
复制
class Test{
 func createDisplayLink(){
 let dispalylink : CADisplayLink = CADisplayLink(target: self, selector: #selector(step))
        dispalylink.add(to: RunLoop.current, forMode: RunLoop.Mode.default)
    }
 @objc func step(displaylink: CADisplayLink){
 let actualFramesPerSecond = 1 / (displaylink.targetTimestamp - displaylink.timestamp)
 print(actualFramesPerSecond)
    }
}

这其中简单展示了其使用。从打印的结果我们能看到帧率是59.9999…也就是常说的60

下面我们看看怎么来完成一个在Label上显示的粒子

typealias Label = UILabel

class XSFps: Label {

private var link: CADisplayLink?

private let defaultFPS = 60.0

private var count: TimeInterval = 0

private var lastTime:TimeInterval = 0

private var lastSecondOfFrameTimes:[TimeInterval] = []

private var frameNumber:UInt = 0

private var frameDuration = 1.0

override var text: String?{

didSet{

textAlignment = .center

font = UIFont.boldSystemFont(ofSize: 13)

self.frame.size = CGSize(width: 25, height: 15)

textColor = UIColor.red

}

}

@objc func toggleDrage(sender:UIPanGestureRecognizer){

let view = sender.view

let newPoint = sender.translation(in: view)

let x:CGFloat = (sender.view?.center.x)! + newPoint.x

let y: CGFloat = (sender.view?.center.y)! + newPoint.y

sender.view?.center = CGPoint(x: x, y: y)

sender.setTranslation(.zero, in: view?.superview)

}

deinit {

if (link != nil) {

#if swift(>=4.2)

link?.remove(from: RunLoop.main, forMode: RunLoop.Mode.common)

#else

link?.remove(from: RunLoop.main, forMode: RunLoopMode.commonModes)

#endif

}

}

override init(frame: CGRect) {

super.init(frame: frame)

for _ in 0 ... Int(defaultFPS) {

lastSecondOfFrameTimes.append(0)

}

addPan()

link = CADisplayLink(target: self, selector: #selector(start(aLink:)))

#if swift(>=4.2)

link?.add(to: RunLoop.main, forMode: RunLoop.Mode.common)

#else

link?.add(to: RunLoop.main

, forMode: RunLoopMode.commonModes)

link?.add(to: RunLoop.main

, forMode: RunLoopMode.commonModes)

#endif

}

private func addPan(){

let pan = UIPanGestureRecognizer(target: self, action: #selector(toggleDrage(sender:)))

self.isUserInteractionEnabled = true

self.addGestureRecognizer(pan)

}

override func removeFromSuperview() {

link?.invalidate()

super.removeFromSuperview()

}

@objc func start(aLink:CADisplayLink){

frameNumber += 1

let currentFrameIndex = Int(frameNumber) % Int(defaultFPS)

lastSecondOfFrameTimes[currentFrameIndex] = (link?.timestamp)!

var droppedFrameCount = 0

let lastFrameTime = CACurrentMediaTime() - frameDuration

for i in 0..<Int(defaultFPS) {

if (1.0 <= lastFrameTime - lastSecondOfFrameTimes[i]) {

droppedFrameCount += 1

}

}

let currentFPS = Int(defaultFPS) - droppedFrameCount

#if (arch(i386) || arch(x86_64)) && debug

text = "\(aLink.timestamp)\n \(aLink.duration) \n\(aLink.framesPerSecond) \n \(currentFPS)"

#else

text = "\(currentFPS)"

#endif

}

required init?(coder aDecoder: NSCoder) {

super.init(coder: aDecoder)

for _ in 0 ... Int(defaultFPS) {

lastSecondOfFrameTimes.append(0)

}

addPan()

link = CADisplayLink(target: self, selector: #selector(start(aLink:)))

#if swift(>=4.2)

link?.add(to: RunLoop.main, forMode: RunLoop.Mode.common)

#else

link?.add(to: RunLoop.main

, forMode: RunLoopMode.commonModes)

#endif

}

}

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大话swift 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档