How to monitor battery level and state changes using swift
You can use the battery state notification UIDeviceBatteryStateDidChangeNotification
and UIDeviceBatteryLevelDidChangeNotification
to be notified when its state changed:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "batteryStateDidChange:", name: UIDeviceBatteryStateDidChangeNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "batteryLevelDidChange:", name: UIDeviceBatteryLevelDidChangeNotification, object: nil)
// Stuff...
}
func batteryStateDidChange(notification: NSNotification){
// The stage did change: plugged, unplugged, full charge...
}
func batteryLevelDidChange(notification: NSNotification){
// The battery's level did change (98%, 99%, ...)
}
Check if battery charging status changes in real time Swift
Basically you did everything to display the current status, now you need to add something that is notified, or checks regularly for said status.
In this case, I believe the best way would be to register to the batteryStateDidChangeNotification
notification, which is only sent by the system when isBatteryMonitoringEnabled
is set to true, as you did in the viewDidLoad
I think adding
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryStatus),
name: UIDevice.batteryStateDidChangeNotification,
object: nil
)
Should do the trick. In the viewDidLoad
for instance.
Check Battery Level iOS Swift
Xcode 11 • Swift 5.1
First just enable battery monitoring:
UIDevice.current.isBatteryMonitoringEnabled = true
Then you can create a computed property to return the battery level:
Battery level ranges from 0.0 (fully discharged) to 1.0 (100%
charged). Before accessing this property, ensure that battery
monitoring is enabled. If battery monitoring is not enabled, battery
state is UIDevice.BatteryState.unknown and the value of this property
is –1.0.
var batteryLevel: Float { UIDevice.current.batteryLevel }
To monitor your device battery level you can add an observer for the UIDevice.batteryLevelDidChangeNotification
:
NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelDidChange), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
Battery level ranges from 0.0 (fully discharged) to 1.0 (100% charged). Before accessing this property, ensure that battery monitoring is enabled.
If battery monitoring is not enabled, battery state is UIDevice.BatteryState.unknown and the value of this property is –1.0.
@objc func batteryLevelDidChange(_ notification: Notification) {
print(batteryLevel)
}
You can also verify the battery state:
var batteryState: UIDevice.BatteryState { UIDevice.current.batteryState }
case .unknown // "The battery state for the device cannot be determined."
case .unplugged // "The device is not plugged into power; the battery is discharging"
case .charging // "The device is plugged into power and the battery is less than 100% charged."
case .full // "The device is plugged into power and the battery is 100% charged."
and add an observer for UIDevice.batteryStateDidChangeNotification
:
NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: UIDevice.batteryStateDidChangeNotification, object: nil)
@objc func batteryStateDidChange(_ notification: Notification) {
switch batteryState {
case .unplugged, .unknown:
print("not charging")
case .charging, .full:
print("charging or full")
}
}
Swift 3 Xcode: How to display battery levels as an integer?
Try this instead:
func someFunction() {
self.infoLabel.text = String(format: "%.0f%%", batteryLevel * 100)
}
For future reference, all string format specifiers are listed here.
how to access device battery level from lock screen
I went through this this tutorial
and this seems to be working perfectly. I made only one change, that is, in info.plist file I added a new property Application does not run in background
& gave it a value YES
.
What is the most concise way to display a changing value with Combine and SwiftUI?
Minimal working example to be pasted inside iPadOS Swift playground.
Basically it’s the give code aligned with the latest changes from SwiftUI and Combine.
use the @Published property wrapper for any properties you want to observe in your view (Docs: By default an ObservableObject synthesizes an objectWillChange publisher that emits the changed value before any of its @Published properties changes.). This avoids the usage of custom setters and objectWillChange.
the cancellable is the output from Publishers.Assign, it can be used to cancel the subscription manually and for best practice, it will be stored in a “CancellableBag” thus cancel the subscription on deinit. This practice is inspired by other reactive frameworks such as RxSwift and ReactiveUI.
I found without turning on the battery level notifications the KVO publisher for battery level will emit just once -1.0.
// iPadOS playground
import SwiftUI
import Combine
import PlaygroundSupport
class BatteryModel : ObservableObject {
@Published var level = UIDevice.current.batteryLevel
private var cancellableSet: Set<AnyCancellable> = []
init () {
UIDevice.current.isBatteryMonitoringEnabled = true
assignLevelPublisher()
}
private func assignLevelPublisher() {
_ = UIDevice.current
.publisher(for: \.batteryLevel)
.assign(to: \.level, on: self)
.store(in: &self.cancellableSet)
}
}
struct ContentView: View {
@ObservedObject var batteryModel = BatteryModel()
var body: some View {
Text("\(Int(round(batteryModel.level * 100)))%")
}
}
let host = UIHostingController(rootView: ContentView())
PlaygroundPage.current.liveView = host
Battery state and level thanks to the background fetch?
Based on the accepted answer, it looks like it wasn't the case, but often these types of questions boil down to trying to defer/cancel intensive, but otherwise discretionary work. If that happens to be the case, I've had great luck with using the NSProcessInfo
low power APIs. There's even a notification for when it becomes enabled, which is particularly useful for cancellation.
Related Topics
How to Have Firebase Automatically Delete Values Older Than 30 Minutes
Rails: Redirect_To 'Myapp://' to Call iOS App from Mobile Safari
Is This a Bug with Mkmapkitdelegate Mapview:Didupdateuserlocation
Memory Leak with "Libbacktracerecording.Dylib" in React Native iOS Application
Crashlytics Does Not Show Crashes
Avassetresourceloaderdelegate Methods Not Working on Device
Why Don't My Views Show Up in Storyboards and Are Greyed Out in the Left Pane
How to Detect Fullscreen Mode Using Avplayerviewcontroller in Swift
Private VS. Fileprivate on Declaring Global Variables/Consts in Swift3
iOS How to Use Uiapplication Launchapplicationwithidentifier Which Is in Private APIs
Drawing Rounded Rect in Core Graphics
Recording from Remoteio: Resulting .Caf Is Pitch Shifted Slower + Distorted
Dequeuereusablecellwithidentifier:Forindexpath: VS Dequeuereusablecellwithidentifier:
Displaying Youtube Video Ads with Youtube Iframe
How to Cancel Usernotifications
How to Get Current Location Using Cllocationmanager in iOS