LoginSignup
7
3

More than 1 year has passed since last update.

【SwiftUI】Combineでバッテリーを監視する

Last updated at Posted at 2022-12-11

はじめに

ゼンリーのアプリを見てたらバッテリー残量が表示されていたのでどうやるのかなと思い、試してみました。
せっかく試したので記事にしておきます。

これをちょっと変えてサンプルアプリを作成します。

サンプルアプリ

充電中 → 緑
それ以外 → 黒
RPReplay_Final1670752390_MP4_AdobeExpress.gif

実装

View

import SwiftUI

struct ContentView: View {
    @StateObject private var viewModel = ViewModel()
    var body: some View {
        batteryShape
            .overlay(batteryText.foregroundColor(.white).blendMode(.difference))
            .overlay(batteryText.blendMode(.hue))
            .overlay(batteryText.foregroundColor(.white).blendMode(.overlay))
    }

    var batteryText: some View {
        Text("\(Int(viewModel.batteryLevel))")
            .font(.system(size: 70, weight: .black))
    }

    var batteryShape: some View {
        ZStack(alignment: .center) {
            RoundedRectangle(cornerRadius: 15)
                .stroke(Color.black, lineWidth: 6)
                .frame(width: 250, height: 120)

            RoundedRectangle(cornerRadius: 10)
                .foregroundColor(viewModel.batteryColor)
                .frame(width: 230 * (viewModel.batteryLevel / 100), height: 100, alignment: .leading)
                .alignmentGuide(HorizontalAlignment.center) { _ in 115 }
        }
    }
}

ViewModel

import Combine
import SwiftUI

final class ViewModel: ObservableObject {
    @Published var batteryLevel: CGFloat = 100

    @Published var batteryColor: Color = .black

    private let device = UIDevice.current

    private var cancellable = Set<AnyCancellable>()

    init() {
        device.isBatteryMonitoringEnabled = true

        device.publisher(for: \.batteryState)
            .sink { [weak self] status in
                guard let self else { return }
                switch status {
                case .charging:
                    self.batteryColor = .green
                case .unplugged:
                    self.batteryColor = .black
                case .full:
                    self.batteryColor = .black
                case .unknown:
                    self.batteryColor = .black
                default:
                    self.batteryColor = .black
                }
            }
            .store(in: &cancellable)

        device.publisher(for: \.batteryLevel)
            .map { CGFloat($0) * 100 }
            .assign(to: &$batteryLevel)
    }
}

おわり

充電中のテキストカラーが純粋な白にできなかったのが悔しいです。。。

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3