Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions myAlarm.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@
objects = {

/* Begin PBXBuildFile section */
5627CB4724CF681800917FD0 /* AlarmListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5627CB4624CF681800917FD0 /* AlarmListTableViewController.swift */; };
5627CB4924CF694600917FD0 /* AlarmDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5627CB4824CF694600917FD0 /* AlarmDetailTableViewController.swift */; };
5627CB4B24CF69B500917FD0 /* SwitchDetailTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5627CB4A24CF69B500917FD0 /* SwitchDetailTableViewCell.swift */; };
5627CB4D24CF715600917FD0 /* Alarm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5627CB4C24CF715600917FD0 /* Alarm.swift */; };
5627CB4F24CF7DAF00917FD0 /* AlarmController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5627CB4E24CF7DAF00917FD0 /* AlarmController.swift */; };
F7C2038C2131AD3400C3FC77 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C2038B2131AD3400C3FC77 /* AppDelegate.swift */; };
F7C203912131AD3400C3FC77 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7C2038F2131AD3400C3FC77 /* Main.storyboard */; };
F7C203932131AD3400C3FC77 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7C203922131AD3400C3FC77 /* Assets.xcassets */; };
F7C203962131AD3400C3FC77 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7C203942131AD3400C3FC77 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
5627CB4624CF681800917FD0 /* AlarmListTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlarmListTableViewController.swift; path = "Settings/Settings/Settings/Views/Custom Views/AlarmListTableViewController.swift"; sourceTree = SOURCE_ROOT; };
5627CB4824CF694600917FD0 /* AlarmDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlarmDetailTableViewController.swift; path = "Settings/Settings/Settings/Views/Custom Views/AlarmDetailTableViewController.swift"; sourceTree = SOURCE_ROOT; };
5627CB4A24CF69B500917FD0 /* SwitchDetailTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchDetailTableViewCell.swift; sourceTree = "<group>"; };
5627CB4C24CF715600917FD0 /* Alarm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Alarm.swift; path = myAlarm/Resources/Alarm.swift; sourceTree = SOURCE_ROOT; };
5627CB4E24CF7DAF00917FD0 /* AlarmController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlarmController.swift; path = myAlarm/Resources/AlarmController.swift; sourceTree = SOURCE_ROOT; };
F7C203882131AD3400C3FC77 /* myAlarm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = myAlarm.app; sourceTree = BUILT_PRODUCTS_DIR; };
F7C2038B2131AD3400C3FC77 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F7C203902131AD3400C3FC77 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
Expand Down Expand Up @@ -63,20 +73,25 @@
F7C203A72131B1D500C3FC77 /* Models */ = {
isa = PBXGroup;
children = (
5627CB4C24CF715600917FD0 /* Alarm.swift */,
);
path = Models;
sourceTree = "<group>";
};
F7C203A82131B1DB00C3FC77 /* Controllers */ = {
isa = PBXGroup;
children = (
5627CB4624CF681800917FD0 /* AlarmListTableViewController.swift */,
5627CB4824CF694600917FD0 /* AlarmDetailTableViewController.swift */,
5627CB4E24CF7DAF00917FD0 /* AlarmController.swift */,
);
path = Controllers;
sourceTree = "<group>";
};
F7C203A92131B1E300C3FC77 /* Views */ = {
isa = PBXGroup;
children = (
5627CB4A24CF69B500917FD0 /* SwitchDetailTableViewCell.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -164,7 +179,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5627CB4924CF694600917FD0 /* AlarmDetailTableViewController.swift in Sources */,
F7C2038C2131AD3400C3FC77 /* AppDelegate.swift in Sources */,
5627CB4D24CF715600917FD0 /* Alarm.swift in Sources */,
5627CB4B24CF69B500917FD0 /* SwitchDetailTableViewCell.swift in Sources */,
5627CB4724CF681800917FD0 /* AlarmListTableViewController.swift in Sources */,
5627CB4F24CF7DAF00917FD0 /* AlarmController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
41 changes: 41 additions & 0 deletions myAlarm/Resources/Alarm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Alarm.swift
// myAlarm
//
// Created by Drew Miller on 7/27/20.
// Copyright © 2020 trevorAdcock. All rights reserved.
//

import Foundation

class Alarm: Codable {

var fireDate: Date
var name: String
var enabled: Bool
var uuid: String

init(fireDate: Date, name: String, enabled: Bool, uuid: String = UUID().uuidString) {
self.fireDate = fireDate
self.name = name
self.enabled = enabled
self.uuid = uuid
}

var fireTimeAsString: String {

let date = DateFormatter()

date.timeStyle = .short

return date.string(from: fireDate)

}
}//end of class

extension Alarm: Equatable {
static func == (lhs: Alarm, rhs: Alarm) -> Bool {
lhs.fireDate == rhs.fireDate && lhs.name == rhs.name && lhs.enabled == rhs.enabled
&& lhs.uuid == rhs.uuid
}
}//end of extension
123 changes: 123 additions & 0 deletions myAlarm/Resources/AlarmController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// AlarmController.swift
// myAlarm
//
// Created by Drew Miller on 7/27/20.
// Copyright © 2020 trevorAdcock. All rights reserved.
//

import Foundation
import UserNotifications

protocol AlarmScheduler: class {
func cancelUserNotifications(for alarm: Alarm)
func scheduleUserNotifications(for alarm: Alarm)
}

class AlarmController: AlarmScheduler {

init() {
loadFromPersistentStore()
}

//Source of Truth
static let shared = AlarmController()

var alarms: [Alarm] = []

func addAlarm(fireDate: Date, name: String, isEnabled: Bool) {
let newAlarm = Alarm(fireDate: fireDate, name: name, enabled: isEnabled)
alarms.append(newAlarm)
if newAlarm.enabled {
scheduleUserNotifications(for: newAlarm)
} else {
cancelUserNotifications(for: newAlarm)
}
saveToPersistentStore()
}

func update(alarm: Alarm, fireDate: Date, name: String, isEnabled: Bool) {
alarm.fireDate = fireDate
alarm.name = name
alarm.enabled = isEnabled
if alarm.enabled {
scheduleUserNotifications(for: alarm)
} else {
cancelUserNotifications(for: alarm)
}
saveToPersistentStore()
}

func delete(alarm: Alarm) {
if let index = self.alarms.firstIndex(where: {$0 == alarm}) {
self.alarms.remove(at: index)
}
cancelUserNotifications(for: alarm)
saveToPersistentStore()
}

func toggleEnabled(for alarm: Alarm) {
alarm.enabled = !alarm.enabled
if alarm.enabled == false {
scheduleUserNotifications(for: alarm)
} else {
cancelUserNotifications(for: alarm)
}
}

func fileURL() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = paths[0]
let fileName = "Alarm.json"
let url = documentDirectory.appendingPathComponent(fileName)
return url
}

func saveToPersistentStore() {
let jsonEncoder = JSONEncoder()

do {
let data = try jsonEncoder.encode(AlarmController.shared.alarms)
try data.write(to: fileURL())
} catch let error {
print("Error saving to persistent store: \(error.localizedDescription)")
}
}

func loadFromPersistentStore() {
let jsonDecoder = JSONDecoder()

do {
let data = try Data(contentsOf: fileURL())
let decodedAlarm = try jsonDecoder.decode([Alarm].self, from: data)
self.alarms = decodedAlarm
} catch let error {
print("Error loading from persistent store: \(error.localizedDescription)")
}
}
}

extension AlarmScheduler {
func cancelUserNotifications(for alarm: Alarm) {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [alarm.uuid])
}

func scheduleUserNotifications(for alarm: Alarm) {
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Alarm"
notificationContent.body = "Your alarm is ringing"


let date = alarm.fireDate
let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)

let request = UNNotificationRequest(identifier: alarm.uuid, content: notificationContent, trigger: trigger)

UNUserNotificationCenter.current().add(request) { (error) in
if let error = error {
print(error)
}
}
}
}
2 changes: 1 addition & 1 deletion myAlarm/Resources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

AlarmController.shared.alarms = AlarmController.shared.loadFromPersisentStore()
// AlarmController.shared.alarms = AlarmController.shared.loadFromPersisentStore()

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (accepted, error) in
if !accepted{
Expand Down
Loading