I am storing some objects in core data that have inherent life spans. I was scheduling local notifications on object creation for this lifespan and then handling the object went the notification fired.
The problem is that the objects can end early. But the local notifications don't know this and still fire at their respective time which leads to confusion. Is there a way to store a pointer to the notification in with the object? So if it ends early it can just cancel it.
I would like to stick with notifications as I need the user to know when it is finished, if it finishes normally. And notifications don't depend on the app running.
Basic question can you store pointers to objects in core data. Second question is if local notifications change memory addresses during their lifespan
I know I could just cancel them all and reschedule the ones needed if one ends early but that just seems wasteful and hopefully there's a better way.
UILocalNotification is not serializable (it doesn't implement NSCoding), so you can't store it persistently with Core Data. I suggest you add the Core Data entities' managedObjectID in serializable form (e.g. as an URL) to the notifications' userInfo property. If you need to delete a specific notification, you search your UIApplications' scheduledLocalNotifications array for the local notification with the corresponding managed object ID in its userInfo property and then cancel that one via cancelLocalNotification:.
Heads up - I've been reviewing this topic, and I'm seeing some conflicting information with the answer from #MrMage :
UILocalNotification does conform to NSCoding per the Apple doc
Here's an answer on stackoverflow that describes how to store the local notification in nsdata which should enable you to store the localnotification as a property in an entity: Delete a particular local notification
Not an expert on this topic though, so any feedback would be great.
Related
I have been looking for tutorials to help me to understand how I can add background app refresh for swift into my watch app, so that my Glance will have fairly up to date data (like the weather app).
So far I haven't found anything and wondered if anyone knew of any advice/examples/tutorials that might benefit me.
You could update your watch app with func updateApplicationContext(_ applicationContext: [String : AnyObject]) throws.
Use this method to transfer a dictionary of data items to the counterpart app. The system sends context data when the opportunity arises, with the goal of having the data ready to use by the time the counterpart wakes up. The counterpart’s session delivers the data to the session:didReceiveUpdate: method of its delegate. A counterpart can also retrieve the data from the receivedApplicationContext property of its session.
updateApplicationContext:error:
This method sends the data in a background task. When the data arrives you could save it inuserDefault or in a class that could be read from your Glance, when your Glance willActivate is called just update the UI with the latest data that arrived in the context.
I have a class that acts as a wrapper around AVPlayer, and one of the functions it serves is to post notifications every 1 and 10 seconds during playback (ie make addPeriodicTimeObserverForInterval: more convenient in the general case).
Previously, the object I was sending with this notification was the player wrapper itself (ie ABPlayer.sharedPlayer). Today I had the need to allow for some objects to only receive notifications about a specific media item's playback. This can be accomplished by sending [[someAVURLAsset URL] absoluteString] as the notification object (when the asset in the AVPlayer is an AVURLAsset, of course).
The prompted the question: is it appropriate for a single notification to, in different situations, post with different types of objects? I understand the value in sending specific objects or sending nil (catch-all), but I don't recall seeing a situation where an alternative type of object could be sent. In my case, though, it seems to make sense.
I could simply send two distinct notifications, but since these are always only ever being sent to notify observers of a single event, and they are always being sent from the same place in code, they simply feel like a single notification.
I realize what I have is possible and working, but I'm curious if there's a compelling reason to avoid this pattern.
As long as the scenarios in which the different object types will be sent to the observers are well understood and documented, there's no technical reason why you can't do it. It may make more contextual sense to post a different notification for each object type. It would certainly help any developers who may end up maintaining your code.
I'm wondering how to deal with this particular issue:
I'm creating a place object, which gets initialized with a geographical lat-long pair. Then I use the iOS geocoder to get an address for that coordinate. I want to set that address to one of my instance variables. However, this asynchronous call doesn't get completed in time, so when I instantiate my object and try to display the address, it hasn't been done yet. What are some strategies to deal with this and similar problems?
Thanks! Merry Christmas!
I don't feel like creating an extensive answer on Christmas Eve so I'll give a brief answer here for now, and edit it later if you've got questions and/or want more details.
Asynchronous requests all have delegate/protocol methods that let you know when the request has failed or succeeded. You should use the NSNotification API and register any object that needs the address for a notification that's triggered when the object completes the request. When the object receives the notification, it can then configure its views or whatever it needs to do. In the requestDidFinish (or whatever) method, you should send the notification.
Check out this article for details (as well as some cool stuff about threading!): http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
The ViewModel can notify the View about property change by raising property change event. If the underlying data (for example, a Plain class which do not implement IPropertyChange) changes, how can ViewModel get notified?
If the underlying data (for example, a Plain class which do not implement IPropertyChange) changes, how can ViewModel get notified?
It cannot, there has to be a mechanism in place to do the notification. The most likely cause is a POCO that is used in one region (or module) of the application is also being used in another, i.e. a loosely coupled master-detail situation. If you are "sharing" the same instance of a POCO like this, then it is unlikely that you haven't also implemented change notification in it. If you have implemented change notification, then a change in one module of the application will automatically be visible to the other module (they are both looking at the same object) and anything that watches for that change notification (like a binding subsystem) will do its thing and pick up the changes.
If you have two separate instances of the same data and one gets updated, the other will not know about it. This also happens when your VM requests data via the Model, and the Model retrieves the data from a disconnected data source like a database or a web service. You don't know when the underlying data has been changed, once again you need to implement a change notification system. You can also take another aproach with this - let the user change the data, then do a fresh grab of the data before saving the user's changes, and if the underlying data has changed while the user was working then you can notify the user and take the appropriate action (or let the user choose the appropriate thing to do).
Does this answer your question? Or do you care to elaborate more about what you are wanting to know?
I'd like to use NSUndoManager in an iPhone application on CoreData (NSManagedObject) objects such that I can save (and later restore) the state of the NSUndoManager if the application exits prematurely (say, due to a phone call coming in). I.e. as opposed to automatically discarding or saving the changes accumulated in the NSUndoManager, I would like to restore them so that the user has the option to explicitly discard or save them when they restart the app.
Has anyone had any experience with this? Can anyone recommend this (or an alternative) approach to managing pending changes in a NSManagedObjectContext when the application is interrupted?
The NSUndoManager does not actually store state, it stores a stack of actions that will restore the state. For example, if you have an object XXX and it has a property name which is a string and you change that name from "Steve" to "Joe", what the NSUndoManager stores is a target, selector and object. The target would be the instance of XXX, the selector would be #selector(setName:) and the object would be #"Steve".
By storing that information, if the undo stack is popped it will call -setName: on the instance of object XXX with the value of #"Steve" and thus restoring its state. There is some additional work done around KVO, etc. but that is the basics.
At first I theorized that you could write out the NSManagedObjectID, the selector (using NSStringFromSelector) and the object to disk and restore them by calling -registerUndoWithTarget: selector: object:. However upon further review of the documentation, there is no way to access the stack to be able to iterate over it.
Note that one possible work-around exists by using separate NSManagedObjectContexts such that some are saved on shutdown whereas others have their changes rolled back. It's not perfect, but I found a suitable solution to my problem with this alternative.