Is there a way to have changes to an object's attribute also "alert" related objects?
The structure we have is as follows:
Image has an attribute called content
Category has a one-to-one relationship to Image
It would be ideal if changes to attributes within the Image object could be detected by the related Category, in a way that the Category would be included in the NSUpdatedObjectsKey of NSManagedObjectContextObjectsDidChangeNotification. I've seen some suggestions indicating that adding a sentinel attribute such as needsUpdate to Category would be a good way to do this, but that seems like a cumbersome way of handling this.
My reasoning for doing this is that I need to reload a tableview whenever a Category changes, or whenever it's associated Image changes, at the moment in my observation method for NSManagedObjectContextObjectsDidChangeNotification I check updated/deleted/inserted objects for Image instances or Category instances, however Image instances are used elsewhere in the app and may have no relationship to a Category instance, in which case it would be a waste to reload the tableview. I could manually loop through the updated/deleted/inserted objects to see if they are Image instances associated with a Category, but that doesn't seem like the best place to do it.
I found that this question is similar to what I am attempting, however it has no answer.
Please let me know if additional information is needed, or if my question is too convoluted.
Edit: Modified to hopefully make it more apparent that I'm interested in Category being aware of changes within the Image object's attributes, rather than a change in the relationship itself.
I would suggest learning about KVO (Key Value Observing) as that framework is designed specifically for this purpose. With KVO you can listen to a specific object for changes on its attributes and then react to them.
However, I question why you are not using a NSFetchedResultsController for this. That is what the NSFetchedResultsController is designed for.
Related
I'm making a simple bank account tracker, for self-instructional purposes. I'm using Core Data to store three entities, related as in the screenshot:
WMMGTransaction objects are simply stored as they are recorded, and extracted as needed to feed tableviews and detail views. This will be done via NSFetchedResultsController and a predicate. I'm using MagicalRecord to access Core Data, if that matters.
My question is this:
When I pass WMMGAccount data from one VC to another, such as when creating a new account, or when selecting one from a list (via delegation as a rule), does it matter if I pass a reference to the entire entity, or can I just use an NSString bearing the .name of the account and identify the account when required with a predicate and an NSFetchedResultsController? I guess this is a strategy question, and may generate discussion, rather than having a cut and dried answer, but I'm wrestling with it, so I thought I'd ask.
It sounds like you're asking if you should pass an object to the code that needs it, or if you should pass information that could be used to look up the same object again.
Unless you need to use the managed object on a different thread or queue, you should always pass the actual object. No sense re-fetching an object you already have. It's extra work and code complexity that (unless there are some unusual extenuating details you didn't mention) won't help in any way.
If you are needing to use the object on a different queue or thread, passing information that can be used to look it up is the correct approach. But in that case-- don't pass the value of one of the properties. Use the managed object ID.
Core Data won't force name values to be unique, while the object's managedObjectID is unique. It's also faster when retrieving the object, because you can use objectForID: or existingObjectForID: instead of performing a fetch.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
KVO and NSMutableArray
Like the title says, I need to be able to detect a change in a mutable array. The reason for this would be to automatically refresh my mapview for an app I'm making as soon as the user adds a new location.
I imagine it would be something like asking if the array is equal to the array's count plus one or the array's count minus one but I don't know how to implement that.
If you need more information before answering please don't hesitate to ask in the comments.
You can use Key-Value Observing for this. For more details check Introduction to Key-Value Observing Programming Guide.
Key-value observing provides a mechanism that allows objects to be
notified of changes to specific properties of other objects. It is
particularly useful for communication between model and controller
layers in an application. (In OS X, the controller layer binding
technology relies heavily on key-value observing.) A controller object
typically observes properties of model objects, and a view object
observes properties of model objects through a controller. In
addition, however, a model object may observe other model objects
(usually to determine when a dependent value changes) or even itself
(again to determine when a dependent value changes).
You can observe properties including simple attributes, to-one
relationships, and to-many relationships. Observers of to-many
relationships are informed of the type of change made—as well as which
objects are involved in the change.
Check this blog about KVO on how to use it. Also check this tutorial. Check this question as well, Key-Value-Observing a to-many relationship in Cocoa
There are many answers to this question.
A popular way would be to use NSNotficationCenter to post notifications everytime your model changes.
You can also use delegation to invoke a method when an object is inserted or Key-Value Observing.
It much depends on your design. If you specify, maybe you can get a more concrete answer.
you could use KVO for that. Personally I don't like NotificationCenter but I guess that personal taste.
see KVO and NSMutableArray
Yet another solution would be Don't Do That. If you the one making the change to the mutable array, then you know you are making a change to the mutable array. If you aren't, then don't vend a mutable array; wrap the array in a class so that any changes must come in through a method that you control.
I often have a UITableViewController with an edit button, which I like to disable when there are no rows in the table. To keep this in sync, I enable/disable the button every time something happens that might update its dataSource - adding the first row, deleting the last row, in viewDidLoad, etc. Whenever I add some new functionality that can affect the contents of the table, I have to remember to incorporate this logic.
Is there some delegate of the UITableView that I can use to simplify this? A way to know whenever the table (or it's dataSource) is modified, where I can check the number of items in the dataSource and enable/disable accordingly.
Alternatively, any other approaches would be welcomed.
You are the data source. So you do know whenever the data source changes, if you care to know. In other words, the reason you're having this problem is that you're treating the model (in the model-view-controller architecture) as an alien being. Instead, treat the model as something of your own. Take charge of your model. For example, is the model an array? Then wrap it in a class of your own, to which all commands to change the array must be given. That way, it can emit a notification whenever it is told to change the array.
It is also possible under certain circumstances to use Key-Value Observing to get notified when something changes, and you could look into it, but with primitives like arrays and dictionaries it is possible that this will be more trouble than it's worth. Again, you're likely to be happier wrapping your model storage in your own class, whose observability via KVO you can manage yourself.
I am working on a shopping list app, and I have a couple of cases where I need to watch for changes to an entity, and respond by making changes to other entities. For example:
When a new store entity is added, I need to create related aisle entities.
When the quantity is changed on a food item to 0 or >0, I need to set a related state flag on the item (ftr, the flag has more than two states, I can't just drop the flag and test for 0).
Based on what I've read so far, the choices seem to be between using key-value observing & registering for a NSManagedObjectContextObjectsDidChangeNotification. What I'm not sure of is which is more suited to my scenarios (or if I should just override the appropriate methods in the related entity classes). Any pointers and/or documentation on when to use these would be much appreciated.
If the flag is a sort of derived property from the quantity information, then your best approach might be to override the setter for the quantity in your managed object subclass and update the flag there. Since the flag is a model property, it makes sense to keep responsibility for its value in the model, rather than in a view controller or other non-model object that's using KVO or responding to notifications.
You can to use NSFetchedResultsController instead of notifications. Also, you can modify your entity to have class methods to add these new records, and manage whatever other modification you need to do.
When getting an object from the DB, should the object's properties also be loaded? There seems to be these approaches.
Create well-formed, fully-loaded objects.
Pro: No need to check if a property has been loaded; it has. Pass it around and don’t worry about parts of the object not being there.
Con: Where do you stop? If an object has an object, and that object has an object, and that object has 40 objects as properties, etc… Do you load the whole DB? Or do you make a decision in the BLL as to what constitutes a well-formed object, and load those properties?
Don’t load any properties that are other objects.
Pro: Quick, no loading unnecessary properties.
Con: Code has to be constantly written to check if properties are populated.
Lazy-loading: only load properties when they are first used.
Pro/Con: Not sure what to say about this approach. It seems intuitively wrong.
Is there another approach? What approach is the best?
And finally, what about properties that can be null? For example, a car may not have a PreviousOwner object. Do you set it to null? An empty PreviousOwner object? Does that property belong in another class then?
There's no easy answer to your question because it depends on what you're trying to achieve.
It looks like you expect a more or less complete object graph to be loaded from the database (i.e. with relationships between multiple object types and the objects themselves stored in the database).
If this is the case, I would look into using the Object Relationship Mapper that's convenient in my language of choice.
As to how much of the object graph is being loaded, the model employed by Apple CoreData's system is objects not yet retrieved are marked as faulty (they call the concept "faulting" - it's described in Limiting the Size of the Object Graph: Faulting. This is a play on the lazy loading concept you described yourself.