What is the correct syntax for NotificationCenter to return batteryLevel and batteryState in Swift 3.1

834 Views Asked by At

I'm a newbie to Swift (using Xcode 8.3.3, Swift 3.1) and I'm trying to display battery level and battery state and update them when the values change. Here's what I have so far:

import UIKit
class ViewController: UIViewController {

@IBOutlet weak var myBatteryPercent: UILabel!
@IBOutlet weak var myBatteryState: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    UIDevice.current.isBatteryMonitoringEnabled = true


    NotificationCenter.default.addObserver(self, selector: Selector(("batteryLevelDidChange:")),
     name: NSNotification.Name.UIDeviceBatteryLevelDidChange,
     object: nil)

    NotificationCenter.default.addObserver(self, selector: Selector(("batteryStateDidChange:")),
     name: NSNotification.Name.UIDeviceBatteryStateDidChange,
     object: nil)

    var batteryLevel: Float {
        return UIDevice.current.batteryLevel
    }

    var batteryState: UIDeviceBatteryState {
        return UIDevice.current.batteryState
    }

    switch batteryState {
    case .unplugged, .unknown:
        myBatteryState.text = "not charging"
    case .charging, .full:
        myBatteryState.text = "charging or full"
    }

    myBatteryPercent.text = "\(Int((batteryLevel) * 100))%"



    func batteryLevelDidChange (notification: Notification) {
        myBatteryPercent.text = "\(Int((batteryLevel) * 100))%"
    }
    func batteryStateDidChange (notification: Notification) {
        switch batteryState {
        case .unplugged, .unknown:
            myBatteryState.text = "not charging"
        case .charging, .full:
            myBatteryState.text = "charging or full"
        }
    }    
}

My app crashes when either the level or state changes generating this error message: [Battery_Display.ViewController batteryLevelDidChange:]: unrecognized selector sent to instance 0x100b0cf10'.

What am I doing wrong?

1

There are 1 best solutions below

3
ninjaproger On BEST ANSWER

Basically you're wrong with a placement of the notification handlers. The handlers are declared inside viewDidLoad method and they are out of scope for NotificationCenter singleton. Just put them out of viewDidLoad and it should work:

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myBatteryPercent: UILabel!
    @IBOutlet weak var myBatteryState: UILabel!
    var batteryLevel: Float {
        return UIDevice.current.batteryLevel
    }

    var batteryState: UIDeviceBatteryState {
        return UIDevice.current.batteryState
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        UIDevice.current.isBatteryMonitoringEnabled = true


        NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelDidChange), name: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil)

        switch batteryState {
        case .unplugged, .unknown:
            myBatteryState.text = "not charging"
        case .charging, .full:
            myBatteryState.text = "charging or full"
        }

        myBatteryPercent.text = "\(Int((batteryLevel) * 100))%"

    }

    func batteryLevelDidChange (notification: Notification) {
        myBatteryPercent.text = "\(Int((batteryLevel) * 100))%"
    }

    func batteryStateDidChange (notification: Notification) {
        switch batteryState {
        case .unplugged, .unknown:
            myBatteryState.text = "not charging"
        case .charging, .full:
            myBatteryState.text = "charging or full"
        }
    }
}