Reputation: 116
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)
}
}
Upvotes: 0
Views: 71
Reputation: 476
@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()
}
}
}
Upvotes: 1