3

Hello I am new to swift and IOS programming. I have set up 6 notifications that are supposed to alert the user 6 times a day depending on the time of day. The alerts are working but for some reason when the app first launches all 6 alerts show up in the notification center at the same time. Any help will be greatly appreciated.

this is the code in the AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.



        let notificationTypes : UIUserNotificationType = UIUserNotificationType.Alert | UIUserNotificationType.Badge
        let notificationSetting : UIUserNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(notificationSetting)

        return true
    }

this is my function for the six different notifications

func prayerAlert (prayerName : String, prayHour : Int, prayMinute : Int) {


        dateComp.year = Int(currentDate.year)
        dateComp.month = Int(currentDate.month)
        dateComp.day = Int(currentDate.day)
        dateComp.hour = prayHour
        dateComp.minute = prayMinute
        dateComp.timeZone = NSTimeZone.systemTimeZone()

        var calender : NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
        var date : NSDate = calender.dateFromComponents(dateComp)!

        var notification : UILocalNotification = UILocalNotification()
        notification.alertBody = prayerName
        notification.fireDate = date



        UIApplication.sharedApplication().scheduleLocalNotification(notification)
    }

and this is where I'm calling the function in the ViewDidLoad

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        pray.setTimeFormat(0)


        self.locationManager.requestAlwaysAuthorization()
        self.locationManager.requestWhenInUseAuthorization()


        if CLLocationManager.locationServicesEnabled() {
            self.locationManager.delegate = self
            self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            self.locationManager.startUpdatingLocation()

        }



        var timesArray = pray.getDatePrayerTimes(currentDate.year, andMonth: currentDate.month, andDay: currentDate.day, andLatitude: locationManager.location.coordinate.latitude, andLongitude: locationManager.location.coordinate.longitude, andtimeZone: pray.timeZone)


            var convertedTime = convertPrayArray(timesArray as NSMutableArray)

            prayerAlert("Time for Fajr", prayHour: convertedTime.hourArray[0], prayMinute: convertedTime.minuteArray[0])
            prayerAlert("Time for SunRise", prayHour: convertedTime.hourArray[1], prayMinute: convertedTime.minuteArray[1])
            prayerAlert("Time for Dhuhr", prayHour: convertedTime.hourArray[2], prayMinute: convertedTime.minuteArray[2])
            prayerAlert("Time for Asr", prayHour: convertedTime.hourArray[3], prayMinute: convertedTime.minuteArray[3])
            prayerAlert("Time for Maghrib", prayHour: convertedTime.hourArray[5], prayMinute: convertedTime.minuteArray[5])
            prayerAlert("Time for Isha", prayHour: convertedTime.hourArray[6], prayMinute: convertedTime.minuteArray[6])


    }
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
gnm1978
  • 137
  • 1
  • 9

1 Answers1

4

Update: Xcode 7.1 • Swift 2.1

The problem is that you are setting the date components to localTime zone instead of the notification.

add this extension NSDate to return the desired components from NSDate()

extension NSDate {
    var minute: Int { return NSCalendar.currentCalendar().component(.Minute, fromDate: self)}
    var hour:   Int { return NSCalendar.currentCalendar().component(.Hour,   fromDate: self)}
    var day:    Int { return NSCalendar.currentCalendar().component(.Day,    fromDate: self)}
    var month:  Int { return NSCalendar.currentCalendar().component(.Month,  fromDate: self)}
    var year:   Int { return NSCalendar.currentCalendar().component(.Year,   fromDate: self)}
    func fireDateAt(hr: Int, min: Int) -> NSDate {
        let date = NSDate()
        return NSCalendar.currentCalendar().dateWithEra(1,
            year: year,
            month: month,
            day: { hr > date.hour || (hr == date.hour && min > date.minute) ? day : day + 1 }(),
            hour: hr,
            minute: min,
            second: 0,
            nanosecond: 0
        )!
    }
}

timeZone Property

The time zone of the notification’s fire date.

The date specified in fireDate is interpreted according to the value of this property. If you specify nil (the default), the fire date is interpreted as an absolute GMT time, which is suitable for cases such as countdown timers. If you assign a valid NSTimeZone object to this property, the fire date is interpreted as a wall-clock time that is automatically adjusted when there are changes in time zones; an example suitable for this case is an an alarm clock.

func prayerAlert (prayerName : String, prayHour : Int, prayMinute : Int) {
    var notification = UILocalNotification()
    notification.timeZone  = NSTimeZone.localTimeZone()
    notification.alertBody = prayerName
    notification.fireDate  = NSDate().fireDateAt(prayHour, min: prayMinute)
    UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • I just tried that and its still the same behavior. Nothing changed – gnm1978 Jan 13 '15 at 02:01
  • still the same exact behavior – gnm1978 Jan 13 '15 at 02:30
  • No it is not the same behavior. that's what you think. – Leo Dabus Jan 13 '15 at 02:35
  • If you show how you declare your dateComp and currentDate would be easier to help you. – Leo Dabus Jan 13 '15 at 02:38
  • I have it declared under the ViewController class – gnm1978 Jan 13 '15 at 02:42
  • Just add a new file to your project (Swift source file) and name it Main.swift. Put this extensions there. And change your code to the updated answer. – Leo Dabus Jan 13 '15 at 02:51
  • I did it exactly as you said and its still the same thing. – gnm1978 Jan 13 '15 at 03:02
  • you need to set your fire date for tomorrow depending of the time of that's it is being set. you can solve it adding one day to your fire date – Leo Dabus Jan 13 '15 at 03:15
  • so if for example the user downloads my app in the morning he wont be able to get notifications until the next day? maybe I'm wrong can you please explain remember I'm still new at this. – gnm1978 Jan 13 '15 at 03:33
  • You just have to compare the time of the notification against the local time and if already happened that day add 1 day otherwise don't. – Leo Dabus Jan 13 '15 at 03:36
  • ok so I just tried to manually fire the notification by manually entering the hour and minute and I didn't get any notifications even tho I set it a couple of minutes in the future – gnm1978 Jan 13 '15 at 03:45
  • I have update the answer. I am sure it will behave as expected. – Leo Dabus Jan 13 '15 at 04:06
  • Perfect now it works!!!! I really appreciate your patience with me even tho I still need to understand exactly what you did and why it has to be this hard. Again thank you for putting up with me – gnm1978 Jan 13 '15 at 04:17
  • I will definitely do that – gnm1978 Jan 13 '15 at 04:45