How to write custom accessors for an NSManagedObject subclass? - iphone

I have a view called Cart. It displays a table of Items. These Items need to persist, so Item subclasses NSManagedObject; values like id, price, etc. are properties whose accessors are #dynamic so that they are automagically generated.
I have another view called Favorites. It displays a table of Items, but they don't need to persist. In fact, this view changes whenever the user logs in with different credentials.
The connection between the two views is that the user can add items to his cart from his favorites. A cart can store Items from different Favorites lists. Favorites lists don't change when the item is added to the cart.
Initially, I made the model for the Favorites view be an NSArray of NSDictionary objects. When the user adds the item to his cart, I create and save the item in Core Data from the NSDictionary key-value pairs. This approach doesn't look very clean or very DRY. Wouldn't it make more sense to make the Favorites view's model be an NSArray of Items?
So now my intent is to implement the Item class so that it will represent the Core Data model (NSManagedObject), but also work with the Favorites view. Being new to Objective-C and iOS development, I really don't know how this would work or look like. It seems that I would need to override the accessors that are magically created for me, but I can't call them at compile time using a super call... Can anyone give me a rough outline of when it would know to return the NSDictionary data or the Core Data data? In the case that it's Core Data data, how do I maintain the same level of efficiency that the magically-generated accessors would have?
Even better, is there a better implementation that is just as DRY or makes more sense? Or am I trying to combine too much functionality into one class? Is the NSArray of NSDictionary objects the best way to go in this case?

You can specify a result type on your fetch request (object, objectID, count, dictionary).
Also, I would not use NSManagedObjects outside of a MOC. You should either have a separate object that you use for memory stuff, or you can use an in-memory persistent store for those objects... or, you can just create a separate MOC as a child to your main database MOC that you use for your in-memory objects.
The advantage of these approaches is that your code does not have to know whether they are backed to the disk or not.
As long as you do not save the MOC, the changes to those objects will never go to disk.
EDIT
NSFetchRequest *fetchRequest = // create the fetch request...
fetchRequest.resultType = NSDictionaryResultType;
Now, when you make the fetch, instead of getting back an array of NSManagedObject you will get back an array of NSDictionary.

Related

iOS / Core Data - Best way to return an array from a NSSet relationship?

I'm creating an app and I'm storing the data using core data. It works fine but I was wondering what's the best way to return a sorted array from an set ?
For example, I have an entity A (Button) that contains a list of entity B (Image). As we all know core data is storing the to-many relationship using an NSSet. But I want to keep track of the initial order so I added a property "order" for that purpose.
The problem is that in my code I need the list of images sorted so in a category file (Button+Create) I created a method like this one :
- (NSArray*)imagesArray
{
return [self.images sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDeacriptorWithKey:#"order" ascending:YES]]];
}
But I don't think that's the best way to do because if a need to access this list from multiple area in my code (different classes) then I need to sort the set x times ...
Is there a way to add an array (property) in my category in order to sort once and then only retrieve the property ?
What are your thoughts about that ?
Thanks
You can add properties to categories:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/ObjectiveC/Chapters/ocAssociativeReferences.html
Here is another example:
How to add properties to NSMutableArray via category extension?
But
Be aware that you will be responsible to observe changes (e.g. via KVO) to the initial coredata NSSet property.
So if changes occur you have to "recalculate" your property properly...
If your target was iOS 5.0 or higher, I would recommend to use Ordered Sets, but due to the fact that you are not, I could imagine using the way described in the links above
I think your approach with order property is correct. I'd rather create a method in my model something like -(NSArray *)sortedItems which would have an NSFetchRequest with appropriate sort descriptor. If you want you can cache the result - save this array in memory. Your NSManagedObject can also have properties that are not stored in the database, just in memory. But I really don't think this is necessary considering the speed and performance of Core Data.

Alternative to NSFetchedResultsController?

Currently I have a UITableView with its data source being an NSFetchedResultsController. The most important thing the NSFetchedResultsController does is automatically update my table if there are any changes, via delegate methods. However, I no longer need to do a fetch to get my entity, call it "Pictures" for now. I have another entity called Folder, and folders have a relationship with Pictures, so every folder has an NSSet pictures.
So instead of fetching all pictures that belong to a certain folder, now I can just do folder.pictures, and that returns what I need, and I can assign that to an array and set that as my tableView source. However, this doesn't give me automatic table updates like an NSFetchedResultsController would.
My question is how can I have the functionality of an NSFetchedResultsController (that is, the delegate methods that automatically update my table) without executing a fetch? I don't need to fetch anymore since I have an NSSet with the desired NSManagedObjects.
What's wrong with the fetched results controller? Just keep it and use the dot notation for relationship sets as well - you get the best of both worlds.
The real advantage of the fetched results controller is actually hidden. It will fetch your objects (folders) alright - but maybe it will not fetch all the relationship attributes (pictures). This is called faulting. It means that core data will get the data in the background if it is needed. It is automatically optimized for speed and good memory usage. For example, the potentially huge array of your datasource will not have to be all in memory at once, something that is unavoidable with an array.
Thus, you really do not want to get rid of the FRC. She is your friend. Stay faithful to her. ;-)

Referencing nsmutablearray to Data Model

I have a design issue which I am trying to analyze in my current project and thought maybe someone could help me figure this out. I have an nsarray object which I filter through predicate, and I want to set that object as my data model through view controller. First, is this a good practice of doing so? Since, I want to have an access of that object through out my transaction. I am not dealing with any database, plist, or core data model at current, these are just custom data model class I have created.
Thanks.
It's very common for a view of some sort to be backed by an NSArray, or an NSMutableArray. (Particularly, a UITableView, which can provide a single cell for each object in your array.)
Depending on the scope of your project, you can either investigate using Core Data for binding your model to your data:
CocoaDevCentral Core Data Overview
Or, for something a bit easier but less robust, you can look into implementing the methods defined in the UITableViewDelegate and UITableViewDataSource protocols, if you want to populate the cells of your table on a per-request basis.

Can I remove an object from the fetchedResultsController without deleting the object from the db?

I have been trying to remove an object from the tableView I am working with without deleting the object from the db, and I can't figure out how to do it.
I have tried setting a predicate on the fetchedResultsController, to filter objects that have a BOOL set to a certain value. Then, when I change that value, I expect that I can get that object to stay in the db, but out of the fetchedResultsController because of the predicate, but alas, that isn't working.
How can I remove an object from my tableView's dataSource (the fetchedResultsController) without deleting it from the core data db completely?
Please help! I've been bashing my head against this for way too long
I've always rolled my own table view data source when I need to weed out fetched results. NSFetchedResultsController objects are great when you want to show everything in your data base, but not so great when you want to weed out some of the data on the fly. I fetch the data, then iterate through the results array looking for the data I want to keep. The good objects get added to a new array, which becomes the basis of my table view data source.
The times I've implemented this, the data manipulation happens in a model object which hands off the array to the UITableViewController subclass that implements UITabelViewDataSource protocol methods. I suppose you could implement this as a subclass of NSFetchedResultsController, but I've never tried that approach.

NSManagedObject for temporary use, how to switch between NSObject and NSManagedObject

Im using a Core Data model for my iPhone app. I have been looking for a way to instantiate or use an Entity outside the ManagedObjectContext. (This should not be done, I know, Im also more looking for a way to not do that, but get the benefits anyway).
My challenge is that I have a view where the user can search for "Persons", all the search results are parsed and put into a Person managedObject then displayed in a list.
If the user clicks a Person from the list, then and only then would I like the Person entity to be persisted to the store, however this requires me to delete all the other results so they don't get persisted along with the desired one. Also to the best of my knowledge, if the user decides to quite the app, the store is persisted, potentially with all current search results mixed in with real user data!
Is there some way I could have a TempPerson NSObject I could use for the search list? Without, however, me having to manually pull the 45 attributes from the temp object and manually set them on the managedObject!
Sort of like:
NSManagedObject aPersonCorrectlyReturnedFromTheStore = (NSManagedObject *)tempPersonOfJustTypeNSObject
I have seen example code from Apple where they build a temporary store to facilitate undo/redo and other stuff on an object that is not yet persisted. This I feel would be overkill in my situation. I just need to display search results until the user selects a Person to persist.
Hope it is clear what Im trying to do, feeling like my Core Data vocabulary isn't quite large enough yet:)
Thanks for any suggestions.
You could create each temporary person object as an NSDictionary or NSMutableDictionary. You can then create a new Person managed object and use the fact that NSManagedObject instances are KVC compliant and use setValuesForKeysWithDictionary:.
New managed objects that are inserted are not actually persisted until you send the managed object context a save: message.
Keep track of them in a collection (set or array) -- you are probably already doing this since you are presenting the search results somehow. Then, delete (deleteObject:) them all except for the one(s) that the user selects.
The deleted managed objects will never be stored.