UILocalNotification always appears as soon as I load my app, regardless of the fire date
Hello I am new to swift and IOS programming. I have set 6 notifications that should inform the user 6 times a day depending on the time of day. Alerts work, but for some reason, the app fires all 6 alerts in Action Center at the same time for the first time. Any help would be greatly appreciated.
this is the code in 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 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 call 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])
}
source to share
Update: Xcode 7.1 • Swift 2.1
The problem is you are setting the date components to the localTime zone instead of the notification.
add this NSDate extension to return the components you want 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
Time zone for the date when notifications were triggered.
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 GMT absolute time, which is fine for things like countdown timers. If you have assigned a valid NSTimeZone object to this property, the fire date is interpreted as wall clock time, which is automatically adjusted when time zones change; an example suitable for this case is 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)
}
source to share