0

I want to add a local notification in my project. In the DetailViewController, I have two labels with date and hour.

Is it possible to add a notification based on this date and hour? If yes, can you explain how to set it?

Code:

DetailViewController :

import UIKit

class DetailViewController: UIViewController, UITableViewDataSource,      UITableViewDelegate {

// MARK: - Outlet

@IBOutlet var imageProfilo: UIImageView!
@IBOutlet var labelNome: UILabel!
@IBOutlet var pillsTable: UITableView!

// MARK: - Variabili
var profilo: ProfiloModel!

// MARK: - Metodi standard del controller

override func viewDidLoad() {
    super.viewDidLoad()

    pillsTable.dataSource = self
    pillsTable.delegate = self

    imageProfilo.layer.cornerRadius = 30


    DataManager.sharedInstance.detail = self

    if let test = profilo {
    //title = profilo!.nome
    labelNome.text = profilo!.nome
    imageProfilo.image = profilo!.immagine

        if profilo!.immagine.size.width > profilo!.immagine.size.height {
            imageProfilo.image = UIImage(CGImage: profilo!.immagine.CGImage, scale: 1.0, orientation: UIImageOrientation.Right)
        } else {
            imageProfilo.image = profilo!.immagine
        }


    } else {

        if !DataManager.sharedInstance.storage.isEmpty {
            profilo = DataManager.sharedInstance.storage[0]
            //title = profiloSos.nome
            labelNome.text = profilo.nome
            imageProfilo.image = profilo.immagine


            if profilo.immagine.size.width > profilo.immagine.size.height {
                imageProfilo.image = UIImage(CGImage: profilo.immagine.CGImage, scale: 1.0, orientation: UIImageOrientation.Right)
            } else {
                imageProfilo.image = profilo.immagine
            }

        } else {
            return
        }

    }


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: UITableView 
 func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return profilo.therapyArra.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PillsCell

    var terapia = profilo.therapyArra[indexPath.row]

    cell.nomeMedicina.text = terapia.nomeMedicina
    cell.data.text = terapia.data
    cell.ora.text = terapia.ora
    cell.dosaggio.text = terapia.dosaggio

    return cell
}


// MARK: - Azioni


// MARK: - Metodi


// MARK: - Navigazione
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "terapia" {
        var cell = sender as! UITableViewCell
        if let indexPath = self.pillsTable.indexPathForRowAtPoint(cell.center) {
            var controller = segue.destinationViewController as! PillsViewController
            controller.therapy = profilo.therapyArra[indexPath.row]
        }

    } else if segue.identifier == "addtherapy" {

        var controller = segue.destinationViewController as! AddPillsController
        controller.profilo = profilo

    }
}

}'

PillsCell :

'import UIKit

class PillsCell: UITableViewCell {



@IBOutlet var nomeMedicina: UILabel!
@IBOutlet var ora: UILabel!
@IBOutlet var data: UILabel!
@IBOutlet var dosaggio: UILabel!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

}

PillsModel :

import UIKit

 class PillsModel: NSObject, NSCoding {

var nomeMedicina :String!
var data :String!
var ora :String!
var dosaggio :String!

init(nomeMedicinaIn:String, dataIn:String, oraIn:String, dosaggioIn:String) {
    nomeMedicina = nomeMedicinaIn
    ora = oraIn
    data = dataIn
    dosaggio = dosaggioIn
}

internal required init(coder aDecoder: NSCoder) {
    self.nomeMedicina = aDecoder.decodeObjectForKey("nomeMedicina") as! String
    self.ora = aDecoder.decodeObjectForKey("ora") as! String
    self.data = aDecoder.decodeObjectForKey("data") as! String
    self.dosaggio = aDecoder.decodeObjectForKey("dosaggio") as! String

}

func encodeWithCoder(encoder: NSCoder) {
    encoder.encodeObject(self.nomeMedicina, forKey: "nomeMedicina")
    encoder.encodeObject(self.ora, forKey: "ora")
    encoder.encodeObject(self.data, forKey: "data")
    encoder.encodeObject(self.dosaggio, forKey: "dosaggio")


}

}

AddPillsController :

import UIKit

class AddPillsController: UIViewController, UITextFieldDelegate, CameraManagerDelegate {

@IBOutlet var fieldNomeMedicina: UITextField!
@IBOutlet var fieldData: UITextField!
@IBOutlet var fieldOra: UITextField!
@IBOutlet var fieldDosaggio: UITextField!

var profilo: ProfiloModel!

override func viewDidLoad() {
    super.viewDidLoad()


    fieldNomeMedicina.delegate = self
    fieldData.delegate = self
    fieldOra.delegate = self



    // Vista accessoria per la tastiera
    var keyboardToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 44))
    keyboardToolbar.barStyle = UIBarStyle.BlackTranslucent
    keyboardToolbar.backgroundColor = UIColor.redColor()
    keyboardToolbar.tintColor = UIColor.whiteColor()
    var flex = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
    var save = UIBarButtonItem(title: "Fatto", style: UIBarButtonItemStyle.Done, target: fieldDosaggio, action: "resignFirstResponder")
    keyboardToolbar.setItems([flex, save], animated: false)
    fieldDosaggio.inputAccessoryView = keyboardToolbar
}


func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder() // chiudere la tastiera nei campi di testo
    return true
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}



@IBAction func annulla(sender: UIButton) {
    dismissViewControllerAnimated(true, completion: nil) // chiude una modal
}


@IBAction func salva(sender: UIButton) {
    if fieldNomeMedicina.text.isEmpty &&
        fieldData.text.isEmpty &&
        fieldOra.text.isEmpty &&
        fieldDosaggio.text.isEmpty{
            //alertView che avverte l'utente che tutti i campi sono obbligatori
            return
    }

    var therapy = PillsModel(nomeMedicinaIn: fieldNomeMedicina.text,
        dataIn: fieldData.text,
        oraIn: fieldOra.text,
        dosaggioIn : fieldDosaggio.text)

    profilo.therapyArra.append(therapy)
    DataManager.sharedInstance.salvaArray()
    DataManager.sharedInstance.detail.pillsTable.reloadData()

    dismissViewControllerAnimated(true, completion: nil)
}


}
Mattias Farnemyhr
  • 4,148
  • 3
  • 28
  • 49
Elis
  • 41
  • 1
  • 7

1 Answers1

1

You should use UILocalNotification. Use your date and time to create a NSDate object and then setup your notification like this:

let notification = UILocalNotification()
notification.fireDate = ... // Add your date here
notification.alertBody = "Alert alert alert!!!"
UIApplication.sharedApplication().scheduleLocalNotification(notification)

Handle the notification in your AppDelegate by overriding the didReceiveLocalNotification method:

func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
    println(notification.alertBody);  // "Alert alert alert!!!"
}
Mattias Farnemyhr
  • 4,148
  • 3
  • 28
  • 49
  • Hi materik, I have added the above code in my AddPillsController after `dismissViewControllerAnimated(true, completion: nil)` but i don't know how to set the object NSDate with the values of the fields **fieldOra** and **filedData**. I want also to add the name and the dosage of the medicine in `notification.alertBody`. Can you help me? – Elis Jun 25 '15 at 16:39
  • Shore. You can add dosage to your ``alertBody`` like this: ``alertBody = "Take this amount of medicine: \(dosage) ml". Then check this answer out for a way to parse your date: http://stackoverflow.com/questions/5979462/problem-combining-a-date-and-a-time-into-a-single-nsdate – Mattias Farnemyhr Jun 25 '15 at 17:19
  • hi, thank for your help, i solved the problem with the date, but when i lunch the app i don't see the notification message for user consent. When i set a notification i don't see the alert message but only a badge in the app icon and a message in notification center. The open/close of app causes the lost of user data. Can you help me? – Elis Jun 26 '15 at 13:56
  • you have to handle the notification in the appdelegate once the app is opened after a notification. you need to override the didrecivelocalnotification method, see https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveLocalNotification: – Mattias Farnemyhr Jun 26 '15 at 14:00
  • Yes i added the code in my AppDelegate file, the code is too long for the comment, see the file at this link: http://d.pr/f/18422 – Elis Jun 26 '15 at 14:11
  • in that file you sent you hadn't override the didrecivelocalnotification? – Mattias Farnemyhr Jun 26 '15 at 14:23
  • sorry i don't understand what code i have to insert in AppDelegate file to override the didrecivelocalnotification. Is my code wrong? – Elis Jun 26 '15 at 14:36
  • Read the link I sent you. You should add that method to the appdelegate. – Mattias Farnemyhr Jun 26 '15 at 15:29
  • hi, i have read your link and i have modified my code (see this link: http://d.pr/f/1ebzT) but there is something wrong because i don't see the alert for user consent when i start the app. Can you help me with the code? – Elis Jun 27 '15 at 09:29
  • I've extended the answer. You should implement that method in your app delegate and then you can do what you want there... – Mattias Farnemyhr Jun 27 '15 at 10:19
  • In what point of AppDelegate i have to add the function? `func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) { println(notification.alertBody); // "Alert alert alert!!!" }` – Elis Jun 27 '15 at 10:33
  • I think i have to add the code before line `DataManager.sharedInstance.startDataManager()`. Is this a correct position? I have to modify something of your code? – Elis Jun 27 '15 at 10:40
  • This is a metod that you need to have your app delegate implement. It doesn't matter where you put it as long as if the app calls for this method your app delegate responds. I can't explain it much better than that unfortunately. – Mattias Farnemyhr Jun 27 '15 at 10:54
  • You don't get a console log? – Mattias Farnemyhr Jun 27 '15 at 10:55
  • I don't understand what you want to say, if you want at this link (http://d.pr/f/1esiJ) you can see the whole project. – Elis Jun 27 '15 at 11:08
  • You have done it correctly. The didReceiveLocalNotification method do get called when you open the app. Now replace the print code with the thing that you want to happen on launch. If you want to, display an UIAlertView or something..... – Mattias Farnemyhr Jun 28 '15 at 11:15
  • hi, i have modified the code in this way: `func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) { UIAlertView(title: notification.alertTitle, message: notification.alertBody, delegate: nil, cancelButtonTitle: "OK").show() }` but when i start the app i don't see the alert for user consent. – Elis Jun 29 '15 at 12:23
  • It should work. Might be that you trying to display it too early. Try adding a delay. – Mattias Farnemyhr Jun 29 '15 at 12:25
  • how can i add a delay to the alert? i have tried to this, but it don't work: http://stackoverflow.com/questions/27990085/nstimer-how-to-delay-in-swift http://stackoverflow.com/questions/28821722/delaying-function-in-swift – Elis Jun 29 '15 at 13:14