Search code examples
iosarraysswiftuilocalnotification

Swift- All UILocalNotification times changed after latest notification is appended to array


I have an array of NSDates that I am iterating through to create an array of UILocalNotification which I then schedule in a batch using scheduledLocalNotifications.

When the notification is created it has the correct date. However, once it is appended to the array, all of the notifications that already exist also take on that date.

func scheduleMessageNotifications() {
    let randomTimes = getSemiRandomTimes() //This function generates an array of unique NSDates which all occur after "now" 
    let notification = UILocalNotification()
    var notifications = [UILocalNotification]()

    for time in randomTimes {

        let nextTime = time
        notification.alertBody = "notification"
        notification.fireDate = nextTime
        //Here the notification has the correct date from randomTimes

        notifications.append(notification)
        //Here the array of notifications all contain the same date; the on that the last notification just had
    }
    UIApplication.sharedApplication().scheduledLocalNotifications = notifications
}

I have tried clean build folder, delete derived data, and restarting my computer. I have also tried to make the loop as simple as possible while still keeping its functionality. I am creating the array of notifications inside of the function and not calling it or sending it elsewhere.

Someone suggested that my time might be a reference and therefore affecting the rest of the objects. But after reading some Apple Documentation (Iterating Over an Array and For-In Loops), I have no way to verify whether that's true or not. (Or what to do about it.) I did attempt

let nextTime = time

but it did not seem to make a difference. Oh, and I know that I am not making more than 64 notifications. (Can't imagine why that would make a difference, but I thought it might come up.)

Any help or ideas would be greatly appreciated.


Solution

  • You are not creating multiple notifications, you are creating one notification and appending it to the array again and again.

    Your resulting array contains multiple references to the same object. If you then change date on that object, all the notifications will have the same date because they are the same object.

    var notifications = [UILocalNotification]()
    
    for time in randomTimes {
        // move notification creation inside the loop
        let notification = UILocalNotification()
    
        let nextTime = time
        notification.alertBody = "notification"
        notification.fireDate = nextTime
        //Here the notification has the correct date from randomTimes
    
        notifications.append(notification)
        //Here the array of notifications all contain the same date; the on that the last notification just had
    }
    

    You might also use map call:

    let notifications: [UILocalNotification] = randomTimes.map { time in
        let notification = UILocalNotification()
    
        let nextTime = time
        notification.alertBody = "notification"
        notification.fireDate = nextTime
    
        return notification
    }