ApplicationManager : allows to add closures that need to be run when app comes to background, foreground or terminates. Example when app comes to foreground : stop playing sound
This commit is contained in:
parent
b1f18c1c1d
commit
fc0b025423
|
@ -31,6 +31,7 @@
|
|||
F81FA006228E09D40028C70F /* TextsCalibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81FA005228E09D40028C70F /* TextsCalibration.swift */; };
|
||||
F81FA008228F52450028C70F /* HomeView.strings in Resources */ = {isa = PBXBuildFile; fileRef = F81FA007228F52450028C70F /* HomeView.strings */; };
|
||||
F81FA00A228F53680028C70F /* TextsHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81FA009228F53680028C70F /* TextsHomeView.swift */; };
|
||||
F81FA00C2298A0190028C70F /* ApplicationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81FA00B2298A0170028C70F /* ApplicationManager.swift */; };
|
||||
F85DC2ED21CFE2F500B9F74A /* BgReading+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DC2E721CFE2F500B9F74A /* BgReading+CoreDataProperties.swift */; };
|
||||
F85DC2EF21CFE2F500B9F74A /* Sensor+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DC2E921CFE2F500B9F74A /* Sensor+CoreDataProperties.swift */; };
|
||||
F85DC2F321CFE3D400B9F74A /* Calibration+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DC2F021CFE3D400B9F74A /* Calibration+CoreDataClass.swift */; };
|
||||
|
@ -170,6 +171,7 @@
|
|||
F81FA005228E09D40028C70F /* TextsCalibration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsCalibration.swift; sourceTree = "<group>"; };
|
||||
F81FA007228F52450028C70F /* HomeView.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = HomeView.strings; sourceTree = "<group>"; };
|
||||
F81FA009228F53680028C70F /* TextsHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsHomeView.swift; sourceTree = "<group>"; };
|
||||
F81FA00B2298A0170028C70F /* ApplicationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationManager.swift; sourceTree = "<group>"; };
|
||||
F85DC2E721CFE2F500B9F74A /* BgReading+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "BgReading+CoreDataProperties.swift"; path = "../Extensions/BgReading+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
F85DC2E921CFE2F500B9F74A /* Sensor+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Sensor+CoreDataProperties.swift"; path = "../Extensions/Sensor+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
F85DC2F021CFE3D400B9F74A /* Calibration+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Calibration+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
|
@ -423,6 +425,7 @@
|
|||
children = (
|
||||
F8B3A7A82265254D004BA588 /* Alerts */,
|
||||
F85DC2F721D2632F00B9F74A /* CoreDataManager.swift */,
|
||||
F81FA00B2298A0170028C70F /* ApplicationManager.swift */,
|
||||
);
|
||||
path = Managers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1046,6 +1049,7 @@
|
|||
F81F9FFC2288C7530028C70F /* NewAlertSettingsViewController.swift in Sources */,
|
||||
F81FA0002289E4990028C70F /* AlertSettingsViewControllerData.swift in Sources */,
|
||||
F8B3A834227F08AC004BA588 /* PickerViewData.swift in Sources */,
|
||||
F81FA00C2298A0190028C70F /* ApplicationManager.swift in Sources */,
|
||||
F8025C0F21D95EC200ECF0C0 /* CGMTransmitterDelegate.swift in Sources */,
|
||||
F8B3A79522635A25004BA588 /* AlertType+CoreDataProperties.swift in Sources */,
|
||||
F8B3A84C227F090E004BA588 /* SettingsViewController.swift in Sources */,
|
||||
|
|
|
@ -11,7 +11,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
// MARK: - Application Life Cycle
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -24,16 +23,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
|
||||
/// set appInForeGround to true
|
||||
UserDefaults.standard.appInForeGround = false
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
|
||||
/// set appInForeGround to true
|
||||
UserDefaults.standard.appInForeGround = true
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
|
@ -45,6 +38,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
// Saves changes in the application's managed object context before the application terminates.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -67,9 +67,6 @@ extension UserDefaults {
|
|||
/// Transmitter Battery Level
|
||||
case transmitterBatteryInfo = "transmitterbatteryinfo"
|
||||
|
||||
// Application
|
||||
// is app in foreground or not
|
||||
case appInForeGround = "appInForeGround"
|
||||
}
|
||||
|
||||
// MARK: - ===== User Configurable Settings ======
|
||||
|
@ -405,17 +402,6 @@ extension UserDefaults {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// is app in foreground or not
|
||||
@objc dynamic var appInForeGround: Bool {
|
||||
get {
|
||||
return bool(forKey: Key.appInForeGround.rawValue)
|
||||
}
|
||||
set {
|
||||
set(newValue, forKey: Key.appInForeGround.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,23 +38,26 @@ public class AlertManager:NSObject {
|
|||
/// playSound instance
|
||||
private var soundPlayer:SoundPlayer?
|
||||
|
||||
// snooze parameters
|
||||
/// snooze parameters
|
||||
private var snoozeParameters = [Int: SnoozeParameters]()
|
||||
|
||||
// helper array with all alert notification identifiers
|
||||
/// helper array with all alert notification identifiers
|
||||
private var alertNotificationIdentifers = [String]()
|
||||
|
||||
// permanent reference to notificationcenter
|
||||
/// permanent reference to notificationcenter
|
||||
private let uNUserNotificationCenter:UNUserNotificationCenter
|
||||
|
||||
// snooze times in minutes
|
||||
/// snooze times in minutes
|
||||
private let snoozeValueMinutes = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 75, 90, 120, 150, 180, 240, 300, 360, 420, 480, 540, 600, 1440, 10080]
|
||||
|
||||
// snooze times as shown to the user, actual strings will be replaced during init
|
||||
/// snooze times as shown to the user, actual strings will be replaced during init
|
||||
private var snoozeValueStrings = ["5 minutes", "10 minutes", "15 minutes", "20 minutes", "25 minutes", "30 minutes", "35 minutes",
|
||||
"40 minutes", "45 minutes", "50 minutes", "55 minutes", "1 hour", "1 hour 15 minutes", "1,5 hours", "2 hours", "2,5 hours", "3 hours", "4 hours",
|
||||
"5 hours", "6 hours", "7 hours", "8 hours", "9 hours", "10 hours", "1 day", "1 week"]
|
||||
|
||||
/// constant for key in ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground - for closure that will stop playing sound
|
||||
private let applicationManagerKeyStopPlayingSound = "alertmanagerstopplayingsound"
|
||||
|
||||
// MARK: - initializer
|
||||
|
||||
init(coreDataManager:CoreDataManager, soundPlayer:SoundPlayer?) {
|
||||
|
@ -83,12 +86,17 @@ public class AlertManager:NSObject {
|
|||
// initialize array of alertNotifications
|
||||
initAlertNotificationIdentiferArray()
|
||||
|
||||
// need to set the alert notification categories, get the existing ones first
|
||||
// need to set the alert notification categories, get the existing categories first, call setAlertNotificationCategories in competionhandler
|
||||
UNUserNotificationCenter.current().getNotificationCategories(completionHandler: setAlertNotificationCategories(_:))
|
||||
|
||||
// observe changes to app status, foreground or background
|
||||
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.appInForeGround.rawValue, options: .new, context: nil)
|
||||
|
||||
// alertManager may have raised an alert with a sound played by soundplayer. If user brings the app to the foreground, the soundPlayer needs to stop playing
|
||||
ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground(key: applicationManagerKeyStopPlayingSound, closure: {
|
||||
if let soundPlayer = soundPlayer {
|
||||
soundPlayer.stopPlaying()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// MARK: - public functions
|
||||
|
@ -240,27 +248,6 @@ public class AlertManager:NSObject {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
// MARK: - overriden functions
|
||||
|
||||
// interested in changes to some of the settings
|
||||
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
|
||||
if let keyPath = keyPath {
|
||||
if let keyPathEnum = UserDefaults.Key(rawValue: keyPath) {
|
||||
switch keyPathEnum {
|
||||
|
||||
case .appInForeGround:
|
||||
// app comes to foreground, if app would still be playing sound, then it doesn't make sense to continue playing, it would mean that app was playing while in the background, most probably for an alert, user opens the app, there's no need to continue alerting the user
|
||||
if let soundPlayer = self.soundPlayer {
|
||||
soundPlayer.stopPlaying()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - private helper functions
|
||||
|
||||
private func createPickerViewData(forAlertKind alertKind:AlertKind) -> PickerViewData {
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
import UIKit
|
||||
|
||||
/// class defines methods to allow running of closures when app comes to foreground or to background
|
||||
class ApplicationManager {
|
||||
|
||||
// MARK: - private properties
|
||||
|
||||
/// list of closures to run when app enters background
|
||||
private var closuresToRunWhenAppDidEnterBackground = [String : (() -> ())]()
|
||||
|
||||
/// list of closures to run when app enters background
|
||||
private var closuresToRunWhenAppWillEnterForeground = [String : (() -> ())]()
|
||||
|
||||
/// list of closures to run when app will terminate
|
||||
private var closuresToRunWhenAppWillTerminate = [String : (() -> ())]()
|
||||
|
||||
/// access to shared instance of ApplicationManager
|
||||
static let shared = ApplicationManager()
|
||||
|
||||
// MARK: - initializer
|
||||
|
||||
/// init is private, to avoid creation
|
||||
private init() {
|
||||
|
||||
// setup notification handling
|
||||
setupNotificationHandling()
|
||||
}
|
||||
|
||||
private func setupNotificationHandling() {
|
||||
|
||||
/// listen for required notifications
|
||||
let notificationCenter = NotificationCenter.default
|
||||
|
||||
/// did enter background
|
||||
notificationCenter.addObserver(self, selector: #selector(runWhenAppDidEnterBackground(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
||||
|
||||
/// will enter foreground
|
||||
notificationCenter.addObserver(self, selector: #selector(runWhenAppWillEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
|
||||
/// will terminate
|
||||
notificationCenter.addObserver(self, selector: #selector(runWhenAppWillTerminate(_:)), name: UIApplication.willTerminateNotification, object: nil)
|
||||
|
||||
}
|
||||
|
||||
// MARK: - public functions
|
||||
|
||||
/// adds closure to run identified by key, when app moved to background
|
||||
///
|
||||
/// closures are stored in a dictionary, key is the identifier
|
||||
func addClosureToRunWhenAppDidEnterBackground(key:String, closure:@escaping () -> ()) {
|
||||
closuresToRunWhenAppDidEnterBackground[key] = closure
|
||||
}
|
||||
|
||||
/// adds closure to run identified by key, when app moved to foreground
|
||||
///
|
||||
/// closures are stored in a dictionary, key is the identifier
|
||||
func addClosureToRunWhenAppWillEnterForeground(key:String, closure:@escaping () -> ()) {
|
||||
closuresToRunWhenAppWillEnterForeground[key] = closure
|
||||
}
|
||||
|
||||
/// adds closure to run identified by key, when app will terminate
|
||||
///
|
||||
/// closures are stored in a dictionary, key is the identifier
|
||||
func addClosureToRunWhenAppWillTerminate(key:String, closure:@escaping () -> ()) {
|
||||
closuresToRunWhenAppWillTerminate[key] = closure
|
||||
}
|
||||
|
||||
// MARK: - private helper functions
|
||||
|
||||
@objc private func runWhenAppDidEnterBackground(_ : Notification) {
|
||||
// run the closures
|
||||
for closure in closuresToRunWhenAppDidEnterBackground {
|
||||
closure.value()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func runWhenAppWillEnterForeground(_ : Notification) {
|
||||
// run the closures
|
||||
for closure in closuresToRunWhenAppWillEnterForeground {
|
||||
closure.value()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func runWhenAppWillTerminate(_ : Notification) {
|
||||
// run the closures
|
||||
for closure in closuresToRunWhenAppWillTerminate {
|
||||
closure.value()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,10 @@ final class CoreDataManager {
|
|||
|
||||
private var log = OSLog(subsystem: Constants.Log.subSystem, category: Constants.Log.categoryCoreDataManager)
|
||||
|
||||
/// constant for key in ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground - for closure that will stop playing sound
|
||||
private let applicationManagerKeySaveChanges = "coredatamanagersavechanges"
|
||||
|
||||
|
||||
// MARK: -
|
||||
|
||||
private let completion: CoreDataManagerCompletion
|
||||
|
@ -96,12 +100,6 @@ final class CoreDataManager {
|
|||
setupCoreDataStack()
|
||||
}
|
||||
|
||||
// MARK: - Notification Handling
|
||||
|
||||
@objc func saveChanges(_ notification: Notification) {
|
||||
saveChanges()
|
||||
}
|
||||
|
||||
// MARK: - Helper Methods
|
||||
|
||||
private func setupCoreDataStack() {
|
||||
|
@ -117,6 +115,9 @@ final class CoreDataManager {
|
|||
// Invoke Completion On Main Queue
|
||||
DispatchQueue.main.async { self.completion() }
|
||||
}
|
||||
|
||||
// when app terminates, call saveChanges, just in case that somewhere in the code
|
||||
ApplicationManager.shared.addClosureToRunWhenAppWillTerminate(key: applicationManagerKeySaveChanges, closure: {self.saveChanges()})
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
|
|
@ -6,6 +6,7 @@ import Foundation
|
|||
///
|
||||
/// where this needs to be checked, create an instance of KeyValueObserverTimeKeeper, example in NightScoutUploader
|
||||
class KeyValueObserverTimeKeeper {
|
||||
|
||||
private var keyObserverKeeper = [String: Date]()
|
||||
|
||||
/// call this to check if last observe of key was at least withMinimumDelayMilliSeconds ago
|
||||
|
|
|
@ -673,7 +673,7 @@ final class RootViewController: UIViewController {
|
|||
}
|
||||
|
||||
// add transmitterBatteryInfo if known
|
||||
if let transmitterBatteryInfo = UserDefaults.standard.transmitterBatteryInfo, let transmitterType = UserDefaults.standard.transmitterType {
|
||||
if let transmitterBatteryInfo = UserDefaults.standard.transmitterBatteryInfo {
|
||||
textToShow += Texts_HomeView.transmitterBatteryLevel + " : " + transmitterBatteryInfo.description
|
||||
// add 1 newline with last connection timestamp
|
||||
textToShow += "\r\n\r\n"
|
||||
|
|
Loading…
Reference in New Issue