返回

在省电模式下解决 iOS 中 RequestAnimationFrame 锁定 30 FPS 的问题

前端

引言

iOS 的省電模式是一項出色的功能,它可以延長設備的電池續航力,但它也會對某些應用程式的效能產生負面影響。一個常見的問題是 RequestAnimationFrame (RAF) 在省電模式下會被鎖定為 30fps。這可能會導致動畫卡頓和使用者體驗不佳。

問題的原因

在省電模式下,iOS 會降低設備的效能以節省電量。這包括降低 CPU 和 GPU 的時脈,從而導致動畫幀率下降。RAF 是瀏覽器用於安排動畫的 API,它依賴於 GPU 的效能。當 GPU 時脈降低時,RAF 的幀率也會相應降低。

解決方案

要解決此問題,有幾種解決方案:

1. 禁用省電模式

最直接的解決方案是禁用省電模式。這將使設備以全速運行,從而允許 RAF 以全幀率運行。然而,這可能會縮短設備的電池續航力。

2. 使用 CADisplayLink

CADisplayLink 是另一個用於安排動畫的 API,它不受省電模式的影響。它與設備的顯示更新週期同步,因此它始終可以以全幀率運行。要使用 CADisplayLink,請執行以下步驟:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create a CADisplayLink
        let displayLink = CADisplayLink(target: self, selector: #selector(update))

        // Add the display link to the run loop
        displayLink.add(to: RunLoop.main, forMode: .common)
    }

    @objc func update(displayLink: CADisplayLink) {
        // Update your animation here
    }
}

3. 使用 Throttled RAF

Throttled RAF 是一種 RAF 的自訂版本,它會根據設備的當前效能動態調整幀率。這可以幫助在省電模式下保持較高的幀率,同時又不犧牲過多的電池續航力。要使用 Throttled RAF,請執行以下步驟:

import UIKit

// Create a custom RAF implementation that throttles the frame rate
class ThrottledRAF {

    private var lastTimestamp: CFAbsoluteTime = 0
    private var interval: CFAbsoluteTime = 0.016667 // 60fps

    func requestAnimationFrame(callback: @escaping (CFAbsoluteTime) -> Void) {
        // Calculate the next frame time
        let now = CFAbsoluteTimeGetCurrent()
        let nextFrameTime = lastTimestamp + interval

        // If the next frame time has not yet passed, wait until it does
        if now < nextFrameTime {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchInterval.milliseconds(UInt64((nextFrameTime - now) * 1000)), execute: {
                callback(nextFrameTime)
            })
        } else {
            // Otherwise, call the callback immediately
            callback(now)
        }

        // Update the last timestamp
        lastTimestamp = now
    }
}

// Create an instance of Throttled RAF
let throttledRAF = ThrottledRAF()

// Use Throttled RAF to schedule your animations
throttledRAF.requestAnimationFrame { timestamp in
    // Update your animation here
}

4. 優化動畫

如果可能的話,應盡量優化動畫以減少對 GPU 的負擔。這包括使用硬體加速的動畫效果,並避免使用複雜的圖形和過渡效果。

結論

通過遵循本文中概述的解決方案,開發人員可以有效解決在 iOS 省電模式下 RAF 鎖定為 30fps 的問題。了解問題的原因並實施適當的解決方案將有助於優化應用程式的效能和為使用者提供出色的動畫體驗。