I have a problem. I have local notifications in my project, here is the code (thanks #leoDabus):
import UIKit
class ViewController: UIViewController {
#IBOutlet var datePicker: UIDatePicker!
#IBOutlet var notificationSwitch: UISwitch!
let localNotification = UILocalNotification()
override func viewDidLoad() {
super.viewDidLoad()
setUpNotificationsOptions()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidAppear(animated: Bool) {
guard let loadedDate = NSUserDefaults().dateForKey("datePicker") else { return }
datePicker.setDate(loadedDate, animated: false)
}
func setUpNotificationsOptions() {
datePicker.datePickerMode = .Time
localNotification.timeZone = NSTimeZone.localTimeZone()
localNotification.repeatInterval = .Day
localNotification.alertAction = "Open App"
localNotification.alertBody = news[0].titleNews
localNotification.soundName = UILocalNotificationDefaultSoundName
}
func toggleNotification() {
if notificationSwitch.on {
localNotification.fireDate = datePicker.date.fireDate
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
} else {
localNotification.fireDate = nil
UIApplication.sharedApplication().cancelLocalNotification(localNotification)
}
}
#IBAction func toggleSwitch(sender: UISwitch) {
toggleNotification()
}
#IBAction func dateChanged(sender: UIDatePicker) {
NSUserDefaults().setDate(sender.date, forKey: "datePicker")
toggleNotification()
} }
extension NSUserDefaults {
func setDate(date: NSDate, forKey:String) {
NSUserDefaults().setObject(date, forKey: forKey)
}
func dateForKey(string:String) -> NSDate? {
return NSUserDefaults().objectForKey(string) as? NSDate
}}
the problem is that my local notification alert Body news[0].titleNews is the result of a parser and it's a value that changes periodically. But with the code above i obtain every day the same string, not the updated one. There is a method to have everyday the updated news? Can I cancel last scheduled notification programmatically and scheduling new one?
Set a unique id in the userInfo property of UILocalNotification and when you get the updated status/news, traverse throught all the scheduled notifications , get your notification with that id you set earlier and now do your work accordingly.
Set your id like the following
localNotification.userInfo = ["notificationID" : "Your Id"]
Code for traversing scheduled notifications
let notificationArr:NSArray? = UIApplication.sharedApplication().scheduledLocalNotifications
notificationArr!.enumerateObjectsUsingBlock({ object, index, stop in
let notification = object as! UILocalNotification;
let userInfo = notification.userInfo! as NSDictionary
let notificationID = userInfo["notificationID"] as! String
if(notificationID == "Your set Id"){
UIApplication.sharedApplication().cancelLocalNotification(notification);
}
})
Related
I'm new to coding and Swift. For my first attempt at an app, I'm attempting to make a mobile music reminder application, in which I can type in the Artist, Album and Release Date and it'll notify me on the release date that the album came out today.
I'm working on the edit button, where if I misspelled the Artist or Album or even got the Release Date wrong, I could go in and edit the already saved information and have that new data saved over the original.
Currently, I'm trying to pass information from one ViewController to another ViewController but I'm having some difficulties.
I need the Artist, Album and Release Date information from the AddfreshreleaseViewController to go the EditfreshreleaseViewController
So far I've only attempted to get the Artist information to pass but I haven't had any luck. I've watched videos and read numerous articles and books but I can't seem to get it to work.
Below is the AddfreshreleaseViewController code:
import UIKit
import CoreData
import UserNotifications
class AddfreshreleaseViewController: UIViewController {
#IBOutlet weak var Artist: UITextField!
/* #IBOutlet weak var textfield = UITextField? (artisttextfield!)
let EditfreshreleaseViewController = segue.destination as! EditfreshreleaseViewController
EditfreshreleaseViewController.receivedString = artisttextfield.text!
}
override func prepare (for segue: UIStoryboardSegue, sender: Any?) {*/
#IBOutlet var artisttextfield: UITextField!
#IBOutlet var albumtextfield: UITextField!
#IBOutlet var releasedatePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
releasedatePicker.minimumDate = Date()
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
var destinationAddfreshreleaseViewController : EditfreshreleaseViewController = segue.destinationAddfreshreleaseViewController as EditfreshreleaseViewController
destinationAddfreshreleaseViewController.ArtistText = Artist.text!
}
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func saveTapped( _ sender: UIBarButtonItem) {
let artist = artisttextfield.text ?? ""
let album = albumtextfield.text ?? ""
let releasedate = releasedatePicker.date
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newRelease = Release_Date(context: context)
newRelease.artist = artist
newRelease.album = album
newRelease.release_date = releasedate as NSDate?
newRelease.release_dateId = UUID().uuidString
if let uniqueId = newRelease.release_dateId {
print("The freshreleaseId is \(uniqueId)")
}
do {
try context.save()
let message = "\(artist)'s new album \(album) releases Today!"
let content = UNMutableNotificationContent()
content.body = message
content.sound = UNNotificationSound.default()
var dateComponents = Calendar.current.dateComponents([.month, .day],
from: releasedate)
dateComponents.hour = 09
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents,
repeats: true)
if let identifier = newRelease.release_dateId {
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: nil)
}
} catch let error {
print("Could not save because of \(error).")
}
dismiss(animated: true, completion: nil)
print("Added a Release Date!")
print("Artist: \(newRelease.artist)")
print("Album: \(newRelease.album)")
print("Release Date: \(newRelease.release_date)")
}
#IBAction func cancelTapped(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
}
Below is the EditfreshreleaseViewController code:
import UIKit
import CoreData
import UserNotifications
class EditfreshreleaseViewController: UIViewController {
#IBOutlet var Artist: UITextField!
var ArtistText = String()
#IBOutlet var artisttextfield: UITextField!
#IBOutlet var albumtextfield: UITextField!
#IBOutlet var releasedatePicker: UIDatePicker!
/*#IBOutlet weak var artist: UILabel! (ArtistTextField!)
var receivedString = ""*/
override func viewDidLoad() {
Artist.text = ArtistText
super.viewDidLoad()
/*artist.text = receivedString*/
releasedatePicker.minimumDate = Date()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func saveTapped( _ sender: UIBarButtonItem) {
let artist = artisttextfield.text ?? ""
let album = albumtextfield.text ?? ""
let releasedate = releasedatePicker.date
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newRelease = Release_Date(context: context)
newRelease.artist = artist
newRelease.album = album
newRelease.release_date = releasedate as NSDate?
newRelease.release_dateId = UUID().uuidString
if let uniqueId = newRelease.release_dateId {
print("The freshreleaseId is \(uniqueId)")
}
do {
try context.save()
let message = "\(artist)'s new album \(album) releases Today!"
let content = UNMutableNotificationContent()
content.body = message
content.sound = UNNotificationSound.default()
var dateComponents = Calendar.current.dateComponents([.month, .day],
from: releasedate)
dateComponents.hour = 09
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents,
repeats: true)
if let identifier = newRelease.release_dateId {
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: nil)
}
} catch let error {
print("Could not save because of \(error).")
}
dismiss(animated: true, completion: nil)
print("Added a Release Date!")
print("Artist: \(newRelease.artist)")
print("Album: \(newRelease.album)")
print("Release Date: \(newRelease.release_date)")
}
#IBAction func cancelTapped(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
}
Any help would be greatly appreciated.
The prepareForSegue function is a UIViewController method that must be overriden by subclasses, in order to pass data between other ViewControllers through a segue.
Try editing your code in AddfreshreleaseViewController to the following. (I've basically removed some code from your viewDidLoad function and added a new one just below it)
override func viewDidLoad() {
super.viewDidLoad()
releasedatePicker.minimumDate = Date()
}
override func prepareForSegue(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? EditfreshreleaseViewController{
destination.ArtistText = Artist.text!
}
}
So as the code shown below, the function loadView 3 is supposed to run 300 seconds(5 minutes) after the user tapped the button. But when I build and run, it does not. I also did a few experiments, I changed the timer to 5 seconds, it worked. So after the app is suspended from iOS system, the NSTimer doesn't run anymore? So what's the problem, how can I fix it?
#IBAction func buttonTapped(sender: AnyObject) {
NSTimer.scheduledTimerWithTimeInterval(300, target: self, selector: #selector(ViewController.loadView3), userInfo: nil, repeats: false)
createLocalNotification()
}
func createLocalNotification() {
let localnotification = UILocalNotification()
localnotification.fireDate = NSDate(timeIntervalSinceNow: 300)
localnotification.applicationIconBadgeNumber = 1
localnotification.soundName = UILocalNotificationDefaultSoundName
localnotification.alertBody = "Hello!"
UIApplication.sharedApplication().scheduleLocalNotification(localnotification)
}
func loadView3() {
label.text = "e89saa"
}
You could try something like this. The approach is, if timer works proceed with same logic, otherwise (probably app is killed or went to background), save firedDate and update UI before showing controller in method viewWillAppear.
#IBAction func buttonTapped(sender: AnyObject) {
NSTimer.scheduledTimerWithTimeInterval(300, target: self, selector: #selector(ViewController.loadView3), userInfo: nil, repeats: false)
createLocalNotification()
}
func createLocalNotification() {
let localnotification = UILocalNotification()
localnotification.fireDate = NSDate(timeIntervalSinceNow: 300)
localnotification.applicationIconBadgeNumber = 1
localnotification.soundName = UILocalNotificationDefaultSoundName
localnotification.alertBody = "Hello!"
UIApplication.sharedApplication().scheduleLocalNotification(localnotification)
// save in UserDefaults fireDate
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(localnotification.fireDate, forKey: "firedDate")
defaults.synchronize()
}
func loadView3() {
// reset in UserDefaults fireDate
let defaults = NSUserDefaults.standardUserDefaults()
defaults.removeObjectForKey("firedDate")
defaults.synchronize()
label.text = "e89saa"
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated) // No need for semicolon
// retrieve fireDate from UserDefaults
let defaults = NSUserDefaults.standardUserDefaults()
let fireDate = defaults.objectForKey("firedData")
// check if we should update UI
if let _ = fireDate as? NSDate! {
if currentDate.compare(firedDate) == NSComparisonResult.OrderedDescending {
loadView3()
}
}
}
I'm a newbie in iOS technology.I'm trying to build an alarm app with swift 2.0 by using UILocalNotification. When I click button, I get the time and date from the UIPickerView. I want to display notification and play sound also.
But both sound and notification are not working. Please help me!
#IBOutlet weak var myPickerView: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
myPickerView.date = NSDate()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func setAlarmClicked(sender: UIButton) {
let dateFormater : NSDateFormatter = NSDateFormatter()
dateFormater.timeZone = NSTimeZone.defaultTimeZone()
dateFormater.timeStyle = .ShortStyle
dateFormater.dateStyle = .ShortStyle
let dateTimeString : NSString = dateFormater.stringFromDate(myPickerView.date)
print("date is \(dateTimeString)")
self.sheduleLocalNotificationWithDate(myPickerView.date)
}
#IBAction func cancelAlarmClicked(sender: UIButton) {
}
func sheduleLocalNotificationWithDate(fireDate : NSDate){
let localNotification : UILocalNotification = UILocalNotification()
localNotification.fireDate = fireDate
localNotification.alertBody = "Alert !!!!"
localNotification.soundName = "minion.mp3"
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
You have to register for local notifications. Add this to your view controller:
override func viewDidAppear() {
super.viewDidAppear()
let settings = UIUserNotificationSettings(forTypes: [.Badge, .Sound, .Alert], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
}
An alert will come up when your view appears for the first time, hit "OK" and your notifications should work. Remember that the user can always disable notifications.
Can anyone help me how to use the state of a UISwitch to turn on/off local notifications declared in Appdelegate.swift ?
Viewcontroller.swift:
#IBOutlet weak var switchButton: UISwitch!
var switchState = true
let switchKey = "switchState"
#IBAction func saveSwitchPressed(sender: AnyObject) {
NSUserDefaults.standardUserDefaults().setBool(switchButton.on, forKey: "switchState")
}
override public func viewDidLoad() {
super.viewDidLoad()
switchButton.on = NSUserDefaults.standardUserDefaults().boolForKey("switchState")
}
AppDelegate.swift
func handleRegionEvent(region: CLRegion) {
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
} else {
// Otherwise present a local notification
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}
}
This should can be accomplished using targetAction
override public func viewDidLoad() {
super.viewDidLoad()
switchButton.on = NSUserDefaults.standardUserDefaults().boolForKey("switchState")
//Set button to observe target action
switchButton.addTarget(self, action: "presentNotification", forControlEvents: UIControlEvents.ValueChanged)
}
func presentNotification() {
//Do notification stuff here
}
I am looking to fire local notifications. I have tried to create this and I was successful, there were no errors but when I run the app in the simulator local notifications don't execute
code in app delegate
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Badge | .Sound, categories: nil))
// play default sound
return true
}
and the view controller
class TechByteSchedulingViewController:UIViewController {
#IBOutlet weak var datePicker: UIDatePicker!
#IBAction func DateChosen(sender: UIButton) {
func sendNotification(sender: UIButton) {
var localNotification = UILocalNotification()
localNotification.fireDate = datePicker.date
localNotification.repeatInterval = .CalendarUnitDay
localNotification.alertBody = "check out your daily byte"
localNotification.alertAction = "Open"
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
application.applicationIconBadgeNumber = 0
}
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
override func viewDidDisappear(animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Base on what I see you implement some function inside of the ButtonAction function which is wrong... you should implement the sendNotficationfunction outside of ButtonAction then called it inside of ButtonAction
class TechByteSchedulingViewController:UIViewController {
#IBOutlet weak var datePicker: UIDatePicker!
#IBAction func DateChosen(sender: UIButton) {
self.sendNotification()
}
func sendNotification() {
var localNotification = UILocalNotification()
localNotification.fireDate = datePicker.date
localNotification.repeatInterval = .CalendarUnitDay
localNotification.alertBody = "check out your daily byte"
localNotification.alertAction = "Open"
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
application.applicationIconBadgeNumber = 0
self.navigationController?.popToRootViewControllerAnimated(true)
}
}