how to send data from notification to application - ios

I use this tutorial for notifications in my app http://www.appcoda.com/local-notifications-ios8/
Each notification has action - Edit. I add Observer for it, in viewDidLoad() method:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleModifyListNotification", name: "modifyListNotification", object: nil)
When press button Edit in notification, app call this method:
func handleModifyListNotification() {
}
for assign notification I use:
func scheduleLocalNotification() {
var dateComp:NSDateComponents = NSDateComponents()
dateComp.year = 2015;
dateComp.month = 02;
dateComp.day = 24;
dateComp.hour = 14;
dateComp.minute = 34;
dateComp.timeZone = NSTimeZone.systemTimeZone()
var calender:NSCalendar? = NSCalendar(calendarIdentifier: NSGregorianCalendar)
var date:NSDate = calender!.dateFromComponents(dateComp)!
var localNotification = UILocalNotification()
localNotification.fireDate = fixNotificationDate(date)
localNotification.alertBody = "Hey, you must go shopping, remember?"
localNotification.alertAction = "View List"
localNotification.category = "shoppingListReminderCategory"
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
But how can I send data to this method to know which notification call this method?

Declare your notification like following,
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleModifyListNotification:", name: "modifyListNotification", object: nil)
with colon in Selector.
and Post your notification like,
NSNotificationCenter.defaultCenter().postNotificationName("modifyListNotification", object: "Your Object Value")
and your function should be,
func handleModifyListNotification(notification: NSNotification) {
NSLog("Object is %#", notification.valueForKey("object") as String!)
}

Related

How to do timeIntervalSinceNow in Swift3?

I was making a notification and watching a tutorial on it and when I typed in:
notification.fireDate = NSDate(timeIntervalSinceNow: 0)
it says
Argument labels '(timeIntervalSinceNow:)' do not match any available
overloads
How do I fix this? Here is my code:
import UIKit
import UserNotifications
class ViewController: UIViewController {
var timer = Timer()
var time = 10
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: Selector(("Notification")), userInfo: nil, repeats: true)
// Do any additional setup after loading the view, typically from a nib.
}
func notification() {
time -= 1
if time <= 0 {
let notification = UILocalNotification()
notification.alertAction = "Call"
notification.alertBody = "You have a call right now"
notification.fireDate = NSDate(timeIntervalSinceNow: 0)
UIApplication.shared.scheduleLocalNotification(notification)
timer.invalidate()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func pushNotification(_ sender: AnyObject) {
let AlertView = UIAlertController(title: "Time for your call!", message: "Press go to continue", preferredStyle: .alert)
AlertView.addAction(UIAlertAction(title: "Go", style: .default, handler: nil))
self.present(AlertView, animated: true, completion: nil)
}
}
Swift 3
let minute:TimeInterval = 11.0 * 60.0;
Date(timeIntervalSinceNow: minute);
for +11 minutes to now.
If you want the fire date to be now, it's just:
notification.fireDate = Date()
As Leo noted elsewhere, the selector is incorrect. It should be:
weak var timer: Timer?
var time = 10
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true)
}
func handleTimer(_ timer: Timer) {
time -= 1
if time <= 0 {
let notification = UILocalNotification()
notification.alertAction = "Call"
notification.alertBody = "You have a call right now"
notification.fireDate = Date()
UIApplication.shared.scheduleLocalNotification(notification)
timer.invalidate()
}
}
You then asked:
that definitely works but now I don't get a notification when I leave the app
You don't get the notification when you leave your app, because the Timer doesn't continue to fire when the app isn't running. It's better to eliminate the timer altogether and just immediately schedule the local notification for the desired time. For example, to schedule a local notification to fire in 10 seconds:
override func viewDidLoad() {
super.viewDidLoad()
scheduleLocalNotification(delay: 10)
}
func scheduleLocalNotification(delay: TimeInterval) {
let notification = UILocalNotification()
notification.alertAction = "Call"
notification.alertBody = "You have a call right now"
notification.fireDate = Date().addingTimeInterval(delay)
UIApplication.shared.scheduleLocalNotification(notification)
}

Call a function using NSTimer

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()
}
}
}

Swift: how to schedule local notification after some seconds

I want my app to schedule a local notification after some seconds it has entered in the background or inactive mode. This is whatIhave done in my view controller, when app enters background mode from it:
class HomeViewController: UITableViewController {
override func viewDidLoad() {
...
let notificationCenter:NSNotificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: #selector(self.appMovedToBackground), name: UIApplicationWillResignActiveNotification, object: nil)
}
func appMovedToBackground() {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
for userInfo in appDelegate.userInfoNotificationPending {
let localNotification = UILocalNotification()
localNotification.userInfo = userInfo
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.alertBody = userInfo["aps"]!["alert"] as? String
localNotification.fireDate = nil
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 2 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
UIApplication.sharedApplication().applicationIconBadgeNumber += 1
}
}
}
}
why doesn't it work?
The didReceiveLocalNotification method in app delegate is called at once as soon as the app enters background. Where am I making the mistake?

Cancel a local notification and schedule a new one

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);
}
})

How to use UILocalNotification to open spesific view containing CoreData

I am developing an application where the user can set a notification reminder to change the password of the CoreData instance to wich the reminder was set.
When the user hits the "First Action" button I want him to be redirected to the second and fourth view.
Heres what Im trying
Relevant code from my AirlineViewController.swift and AppDelegate.swift
AirlineViewController.swift:
#IBAction func buttonTapped(sender: AnyObject) {
NSNotificationCenter.defaultCenter().addObserver(self, selector:"showAMessage:", name: "actionOnePressed", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector:"drawAShape:", name: "actionTwoPressed", object: nil)
var dateComp:NSDateComponents = NSDateComponents()
dateComp.year = 2015;
dateComp.month = 08;
dateComp.day = 03;
dateComp.hour = 21;
dateComp.minute = 03;
dateComp.timeZone = NSTimeZone.systemTimeZone()
var calender:NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var date:NSDate = calender.dateFromComponents(dateComp)!
var notification:UILocalNotification = UILocalNotification()
notification.category = "FIRST_CATEGORY"
notification.alertBody = "Hi, I am a notification"
notification.fireDate = date
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
func drawAShape(notification:NSNotification){
println("drawAShape")
var view:UIView = UIView(frame:CGRectMake(10, 10, 100, 100))
view.backgroundColor = UIColor.redColor()
self.view.addSubview(view)
println("drawAShape")
}
func showAMessage(notification:NSNotification){
var message:UIAlertController = UIAlertController(title: "A Notification Message", message: "Hello there", preferredStyle: UIAlertControllerStyle.Alert)
message.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(message, animated: true, completion: nil)
}
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Actions
var firstAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
firstAction.identifier = "FIRST_ACTION"
firstAction.title = "First Actions"
firstAction.activationMode = UIUserNotificationActivationMode.Foreground
firstAction.destructive = true
firstAction.authenticationRequired = false
var secondAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
secondAction.identifier = "SECOND_ACTION"
secondAction.title = "Second Actions"
secondAction.activationMode = UIUserNotificationActivationMode.Foreground
secondAction.destructive = false
secondAction.authenticationRequired = false
var thirdAction:UIMutableUserNotificationAction = UIMutableUserNotificationAction()
thirdAction.identifier = "THIRD_ACTION"
thirdAction.title = "Third Actions"
thirdAction.activationMode = UIUserNotificationActivationMode.Background
thirdAction.destructive = false
thirdAction.authenticationRequired = false
//Category
var firstCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
firstCategory.identifier = "FIRST_CATEGORY"
let defaultActions:NSArray = [firstAction, secondAction, thirdAction]
let minimalActions:NSArray = [firstAction, secondAction]
firstCategory.setActions(defaultActions as [AnyObject], forContext: UIUserNotificationActionContext.Default)
firstCategory.setActions(minimalActions as [AnyObject], forContext: UIUserNotificationActionContext.Minimal)
//NSSet of all our categories
let categories:NSSet = NSSet(objects: firstCategory)
let types:UIUserNotificationType = UIUserNotificationType.Alert | UIUserNotificationType.Badge
let mySettings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: categories as Set<NSObject>)
UIApplication.sharedApplication().registerUserNotificationSettings(mySettings)
return true
}
func application(application: UIApplication!,
handleActionWithIdentifier identifier:String!,
forLocalNotification notification:UILocalNotification!,
completionHandler: (() -> Void)!){
if (identifier == "FIRST_ACTION"){
NSNotificationCenter.defaultCenter().postNotificationName("actionOnePressed", object: nil)
}else if (identifier == "SECOND_ACTION"){
NSNotificationCenter.defaultCenter().postNotificationName("actionTwoPressed", object: nil)
}
completionHandler()
}
The problem with this code is that it just opens the last view or the first if the app is completely closed.
Can anybody help me
There is no built-in mechanism I know of to have UILocalNotification take you directly to a specific part of your app's UI.
You can attach a userInfo dictionary to a UILocalNotification before you post it.
You can then interrogate that userInfo dictionary, figure out where it is supposed to take the user in your UI, and write custom code to take the user to that part of the app UI.
I'm doing exactly that for an app I'm developing right now for a client. I embed the information needed to let the app invoke the screen in question. (The specifics depend on the design of the app, which uses a custom forms description file to describe the hierarchy of view controllers in the app.)

Resources