Search code examples
iosswiftnotificationsalarm

having trouble implementing notifications to my alarm app


I have created an alarm app that looks similar to ios alarm app and the cells and the tableview also look similar to it . The cells are having 2 things label & switch Button so that when I turn on the button the alarm gets activated at the cell's label time.

There is a triggerAlarm() function which keeps track of time and loops through the items array which is of type [Item]() (Item is a class of type NSManagedObject which saves the data. It has 2 attributes time: String & isOn: Bool).

The problem is that the Timer method in viewDidLoad() is not running through that loop in triggerAlarm() func but prints realTime . The loop is supposed to compare the realTime with items array and call the notificationTrigger() func if the isOn property is true but its not happening.

Xcode is not showing any error either.

Here is the code :

import UIKit
import UserNotifications

class TableViewController: UITableViewController {

    var realTime  = String()
    var items     = [Item]()

    override func viewDidLoad() {
        super.viewDidLoad()
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge], completionHandler: {didAllow, error in})

    }

    override func viewWillAppear(_ animated: Bool) {

        getData()
        tableView.reloadData()

    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

        let row = items[indexPath.row]

        cell.timeLbl.text   = row.time
        cell.switchBtn.isOn = row.isOn

        cell.callback = { newValue in
            row.isOn = newValue
            (UIApplication.shared.delegate as! AppDelegate).saveContext()
        }
        return cell
    }

    func getData() {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        do {
             items = try context.fetch(Item.fetchRequest())
        }catch{
            print("\(error)")
        }
    }

    func triggerAlarm() {
        realTime = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .short)
        print(realTime)
        for i in 0..<items.count {
            if (items[i].time!) == realTime && items[i].isOn == true{
                print(time)
                self.notificationTrigger()
            }else {
                return
            }
        }
    }

    func notificationTrigger() {
        let content      = UNMutableNotificationContent()
        content.title    = "time is up \(time)"
        content.subtitle = "asdf"
        content.body     = "qwer"
        content.badge    = 0

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
        let request = UNNotificationRequest(identifier: "customNotification", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)

    }
}

Solution

  • @objc func triggerAlarm() {
        realTime = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .short)
        print(realTime)
        for i in 0..<items.count {
            if (items[i].time!) == realTime && items[i].isOn == true{
                print(time)
                self.notificationTrigger()
            }else {
                return
            }
        }
    }
    

    Here you are using return in else. So instead of breaking the loop for the current iterartion(I suppose you want to achieve this), it is returning from the whole method call. Instead use:-

    continue

    Or better just omit the else part

     @objc func triggerAlarm() {
        realTime = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .short)
        print(realTime)
        for i in 0..<items.count {
            if (items[i].time!) == realTime && items[i].isOn == true{
                print(time)
                self.notificationTrigger()
            }
        }
    }