UIApplication.sharedApplication.scheduledLocalNotifications is always empty - ios

Even if I add a new local notification right before, the attribute is empty. I found a lot of post (and just one on stack overflow) - but nobody has solved this problem.
My useless is, that I want to delete a local notification. That's why I want to iterate over the array and compare the hash value of my notification to delete and the current iterator object.
The notification fires correctly.
Add notification to the array
UIApplication.sharedApplication().scheduleLocalNotification(newNotification)
Read the array
for notification in application.scheduledLocalNotifications {
if notification.hashValue == hashValue {
application.cancelLocalNotification(notification as! UILocalNotification)
NSLog("Unsheduled local notification for \(notification.alertBody!)")
}
}
Thanks for your help.

Seems I have not been first to be stucked on it..
But seems answer is much closer than I tought.
Cmd + LPM
public var scheduledLocalNotifications: [UILocalNotification]? // setter added in iOS 4.2
The property is just form of setter. And probably was never intended to get scheduled notifications

It seems that checking the UIApplication's scheduledLocalNotifications array is fairly unreliable.
Most people seem to recommend just keeping your own list as well, and querying that.
Firstly, that array will only contain notifications that are scheduled after the current date, so any that have been registered that are in the past or any that have already fired, will not be added.
For me, that was not the problem, the notificatiosn I was registering were definitely in the future, but still didn't appear in the list. The best answer I could find is:
Having similar issues right now. My guess here is that iOS does not schedule the notifications immediately but only at the end of the current run loop. I am running into these problems when setting the scheduledLocalNotifications property several times in the same run loop and changes don't seem to be updated accordingly. I think I will just keep a copy of the local notifications array myself and only set scheduledLocalNotifications and never read it.
(source)

Related

Fast way of finding scheduled notifications

Is there a fast and efficient way of finding scheduled notifications? Find list of Local Notification the app has already set discusses going through the list, which is what I did:
// To avoid duplicate notifications, check whether there are already scehduled notifications with the same fireDate, reminderName and calendar name.
if let definiteDueDateComponents = reminder.dueDateComponents, definiteDueDate = definiteDueDateComponents.date, definiteScheduledNotifications = UIApplication.sharedApplication().scheduledLocalNotifications {
for notification in definiteScheduledNotifications {
if notification.fireDate?.compare(definiteDueDate) == .OrderedSame {
// Check whether there is already a notification set up for definiteDueDate?
// If so, check whether the notification is actually for the same item that I want to set up here.
}
}
}
This, however, may become inefficient, especially if I have many items that I want to check against (run the above code) before I schedule them and also if I already have various scheduled notifications.
Has anybody experimented with creating a dictionary (hash table) of scheduled notifications? If so, when do you create it and recreate it? Is it cumbersome trying to keep the hash table in synch with UIApplication.sharedApplication().scheduledLocalNotifications?
Even if you have 10000 scheduled notifications you would probably not be able to detect the amount of time it took to iterate through them with your eyes. You'd have to log the time before and after and calculate the difference, and it would likely be less than 1/1000 of a second.
This is a case of "premature optimization". Use a for loop and be done with it.
If you have more than 10000 scheduled notifications then you need to rethink your design.

How to get notified when some proprerty of PFObject changed?

Im using parse.com and I wonder if there is a possible approach to get notified when PFObject on parse change one of his properties. The only sollution that I see is to use Push notifications and when notification arrive a refresh the object. Is this the bes possible way or there is a better one?
Thanks.
I don't think there is a way to do this. As you suggested I would simply refresh the PFObject before using it
You could create cloud-code .beforeSave / .afterSave function, which will trigger notification to be send. However it could be very wasteful, so perhaps depending on your timing needs you may also query for objects with recent updatedAt dates every once in a while ?
Parse.Cloud.beforeSave("className", function(request, response) {
if (request.object.existed() ) {
//this is update of already existing object
//... check if change has been done and trigger new notification
}
});

Identifying old and new values on changed objects with NSManagedObjectContextWillSaveNotification

I am trying to track changes to objects in a core data context, tracking the name of properties that have changed along with the old and new values.
I've registered for NSManagedObjectContextWillSaveNotification to receive a notification when a save is about to occur, and can pull out the inserted/updated/deleted objects from the context... I can then see the changed values using .changedValues.
However, I am having difficulties retrieving the old values...
As an example, I have an object that tracks a position, and so one of the changes comes back with:
po [obj changedValues]
{
originX = 260;
originY = 180;
}
This gives me the new values for the properties that have changed on the object. To try and get the old values, I'm then using changedValuesForCurrentEvent, which according to the docs should return
"a dictionary containing the keys and old values of persistent
properties that have changed since the last posting of
NSManagedObjectContextObjectsDidChangeNotification"
However, when I try this, it is coming back empty...:
po [obj changedValuesForCurrentEvent]
{
}
How can I capture the old and new values?
You're mixing up your notifications. NSManagedObjectContextObjectsDidChangeNotification gets called any time you change values on a managed object, even though you haven't saved changes yet. NSManagedObjectContextWillSaveNotification gets called later on when you save. So the sequence is:
You change some attributes --> NSManagedObjectContextObjectsDidChangeNotification is posted, and you can use changedValuesForCurrentEvent to see what changed.
Later, you save changes. NSManagedObjectContextWillSaveNotification is posted. You can call changedValuesForCurrentEvent, but it's not helpful because it returns changes since the last did-change notification. There are no changes since the last did-change notification. If there were, you would have received another one. That method is documented to be useful on a did-change notification, not on a will-save notification.
If you want the old values and you want to get them when the will-save notification is posted, you have a couple of options:
Listen for NSManagedObjectContextObjectsDidChangeNotification. Cache information about changes in some collection object (probably NSDictionary). Then when NSManagedObjectContextWillSaveNotification happens, look up those changes, process them, and clear the change cache. OR...
When you get NSManagedObjectContextWillSaveNotification, create a second local managed object context. Since this is a will save notification, you can still fetch the old values. So, fetch each object that's getting saved and compare the before and after values to see what's different.
Although this question is 4 years old, Eddie's answer was very helpful. I made a little change to his answer. All the credits goes to him.
object.setValuesForKeys(object.committedValues(forKeys: object.changedValues().map { $0.key }))
I know this question is old, but there is a better way than the accepted answer. You can access the previous values via committedValues(forKeys:) in combination with changedValues(). There is no need to handle NSManagedObjectContextObjectsDidChangeNotification or to create another managed object context.
Here is some sample code that I use:
// For some reason, the Swift compiler chokes on the type of object.changedValues().keys.
// It should be of type [String], but it complains that it is of type `Dictionary<String, Any>.Keys`
// which is useless. Ah, the joys of Apple programming...
// Work around that like so:
var changedKeys = [String]()
for (key, _) in object.changedValues() {
changedKeys.append(key)
}
let oldData = object.committedValues(forKeys: changedKeys)
Sounds like you should call "changedValuesForCurrentEvent" only when you receive your "NSManagedObjectContextWillSaveNotification" notification.
And if "changedValuesForCurrentEvent" still returns a null dictionary or object, check to see if the notification had anything useful in it's "userInfo" dictionary itself. It also may be that there has not been a NSManagedObjectContextObjectsDidChangeNotification" posted, like you posted from the docs up there.

iOS NSManagedObjectContext - is it possible to get or send a notification when all changes is saved?

I use Core Data - and I have registered and is listening for NSManagedObjectContextDidSaveNotification:s I have a collection of data (from JSON), that I want to save, and after all objects is saved, I would like to get some kind of notification. It currently seems like this notification is sent after every object is saved. Is there some kind of built in solution for getting my desired notification? If not, how could/should I do it?
There's no built-in notification that gets posted after you've saved a specific batch of objects. Core Data really has no idea how many objects are in your collection, so it has no way to know that you've reached the end of it.
You'll get NSManagedObjectContextDidSaveNotification every time you call save: on the managed object context. You could just wait to save until you've handled all of the objects, which would mean just one NSManagedObjectContextDidSaveNotification.
A better solution is to post your own notification when you know that you've finished the collection. Define a string constant called something like JSONUpdatesCompleteNotification, and post a notification with that name after your last save: call.
NSString *JSONUpdatesCompleteNotification = #"JSONUpdatesCompleteNotification";
Then later, when you know you're done,
[[NSNotificationCenter defaultCenter] postNotificationName:JSONUpdatesCompleteNotification object:self];
Make sure you observe this notification anywhere you need to know about it, and you're done.

NSNotification if data changes

Let's assume that I have a program that parses a RSS feed.
I have a method that runs in a thread which keeps checking for updates. If updates is found a NSNotification is created. Is this a stupid implementation?
And is it possible to pass custom parameters within a NSNotification, such as the elementId that was updated.
Sounds like a good plan to me. Yes, you can pass user data.
See NSNotification's notificationWithName:object:userInfo:. The userInfo is an NSDictionary so you can pass whatever you like around.

Resources