diff --git a/examples/platform_channel/macos/Runner/MainFlutterWindow.swift b/examples/platform_channel/macos/Runner/MainFlutterWindow.swift index 16df5f6335..239c019ddf 100644 --- a/examples/platform_channel/macos/Runner/MainFlutterWindow.swift +++ b/examples/platform_channel/macos/Runner/MainFlutterWindow.swift @@ -5,15 +5,16 @@ import Cocoa import FlutterMacOS -class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeDelegate { +class MainFlutterWindow: NSWindow { private let powerSource = PowerSource() - private let stateChangeSource = PowerSourceStateChangeHandler() + private let stateChangeHandler = PowerSourceStateChangeHandler() private var eventSink: FlutterEventSink? override func awakeFromNib() { let flutterViewController = FlutterViewController() let windowFrame = self.frame self.contentViewController = flutterViewController + self.displayIfNeeded() self.setFrame(windowFrame, display: true) // Register battery method channel. @@ -21,18 +22,18 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD let batteryChannel = FlutterMethodChannel( name: "samples.flutter.io/battery", binaryMessenger: registrar.messenger) - batteryChannel.setMethodCallHandler({ [weak self] (call, result) in + batteryChannel.setMethodCallHandler { [powerSource = self.powerSource] (call, result) in switch call.method { case "getBatteryLevel": - if self?.powerSource.hasBattery() == false { - result(FlutterError( - code: "NO_BATTERY", - message: "Device does not have a battery", - details: nil)) + guard powerSource.hasBattery() else { + result( + FlutterError( + code: "NO_BATTERY", + message: "Device does not have a battery", + details: nil)) return } - let level = self?.powerSource.getCurrentCapacity() - if level == -1 { + guard let level = powerSource.getCurrentCapacity() else { result( FlutterError( code: "UNAVAILABLE", @@ -44,7 +45,7 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD default: result(FlutterMethodNotImplemented) } - }) + } // Register charging event channel. let chargingChannel = FlutterEventChannel( @@ -57,25 +58,7 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD super.awakeFromNib() } - func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) - -> FlutterError? - { - self.eventSink = events - self.emitPowerStatusEvent() - self.stateChangeSource.delegate = self - return nil - } - - func onCancel(withArguments arguments: Any?) -> FlutterError? { - self.stateChangeSource.delegate = nil - self.eventSink = nil - return nil - } - - func onPowerSourceStateChanged() { - self.emitPowerStatusEvent() - } - + /// Emit a power status event to the registered event sink. func emitPowerStatusEvent() { if let sink = self.eventSink { switch self.powerSource.getPowerState() { @@ -88,5 +71,27 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD } } } - +} + +extension MainFlutterWindow: FlutterStreamHandler { + func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) + -> FlutterError? + { + self.eventSink = events + self.emitPowerStatusEvent() + self.stateChangeHandler.delegate = self + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + self.stateChangeHandler.delegate = nil + self.eventSink = nil + return nil + } +} + +extension MainFlutterWindow: PowerSourceStateChangeDelegate { + func didChangePowerSourceState() { + self.emitPowerStatusEvent() + } } diff --git a/examples/platform_channel/macos/Runner/PowerSource.swift b/examples/platform_channel/macos/Runner/PowerSource.swift index d1b14d830c..c465b2a611 100644 --- a/examples/platform_channel/macos/Runner/PowerSource.swift +++ b/examples/platform_channel/macos/Runner/PowerSource.swift @@ -12,9 +12,13 @@ enum PowerState { } /// A convenience wrapper for an IOKit power source. -class PowerSource { +final class PowerSource { let info = IOPSCopyPowerSourcesInfo().takeRetainedValue() - lazy var sources = IOPSCopyPowerSourcesList(info).takeRetainedValue() as Array + let sources: Array + + init() { + sources = IOPSCopyPowerSourcesList(info).takeRetainedValue() as Array + } func hasBattery() -> Bool { return !sources.isEmpty @@ -22,7 +26,7 @@ class PowerSource { /// Returns the current power source capacity. Apple-defined power sources will return this value /// as a percentage. - func getCurrentCapacity() -> Int { + func getCurrentCapacity() -> Int? { if let source = sources.first { let description = IOPSGetPowerSourceDescription(info, source).takeUnretainedValue() as! [String: AnyObject] @@ -30,7 +34,7 @@ class PowerSource { return level } } - return -1 + return nil } /// Returns whether the device is drawing battery power or connected to an external power source. @@ -54,11 +58,11 @@ class PowerSource { } protocol PowerSourceStateChangeDelegate: AnyObject { - func onPowerSourceStateChanged() + func didChangePowerSourceState() } /// A listener for system power source state change events. Notifies the delegate on each event. -class PowerSourceStateChangeHandler { +final class PowerSourceStateChangeHandler { private var runLoopSource: CFRunLoopSource? weak var delegate: PowerSourceStateChangeDelegate? @@ -66,10 +70,10 @@ class PowerSourceStateChangeHandler { let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) self.runLoopSource = IOPSNotificationCreateRunLoopSource( { (context: UnsafeMutableRawPointer?) in - let weakSelf = Unmanaged.fromOpaque( + let unownedSelf = Unmanaged.fromOpaque( UnsafeRawPointer(context!) ).takeUnretainedValue() - weakSelf.delegate?.onPowerSourceStateChanged() + unownedSelf.delegate?.didChangePowerSourceState() }, context ).takeRetainedValue() CFRunLoopAddSource(CFRunLoopGetCurrent(), self.runLoopSource, .defaultMode)