SwiftUI、Battery & NotificationCenter

battery_status

想要知道目前行動裝置的電池電量與電池狀態(例如:充電或未充電),可以透過 UIDevice 的 batteryLevel 與 batteryState 取得。但是要在值有變化時會主動通知我們,就需要透過 NotificationCenter 來完成。

在 SwiftUI 中要做到這一點,可以呼叫 NotificationCenter 的 publisher 函數,這樣就不再需要使用 #selector 再加上一個 @objc 修飾的函數來設定 callback function,讓整個語法上簡潔許多。下面的程式碼可以在電池電量或是充電狀態改變時通知 App 要更新內容了。

struct ContentView: View {
    @State private var level: Float = 0
    @State private var state = ""
    
    private let levelPublish = NotificationCenter.default.publisher(
        for: UIDevice.batteryLevelDidChangeNotification
    )
    private let statePublish = NotificationCenter.default.publisher(
        for: UIDevice.batteryStateDidChangeNotification
    )
    
    var body: some View {
        HStack {
            Text(state)
            Text("\(Int(level * 100)) %")
        }
        .onReceive(levelPublish) { output in
            // 電池電量
            level = UIDevice.current.batteryLevel
        }
        .onReceive(statePublish) { output in
            // 充電狀態
            state = batteryState()
        }
        .onAppear {
            UIDevice.current.isBatteryMonitoringEnabled = true
            level = UIDevice.current.batteryLevel
            state = batteryState()
        }
        .padding()
    }
    
    private func batteryState() -> String {
        switch UIDevice.current.batteryState {
        case .charging:
            return "充電中"
        case .full:
            return "滿電"
        case .unplugged:
            return "使用電池"
        case .unknown:
            return "未知"
        @unknown default:
            fatalError()
        }
    }
}

發表迴響