Indexed Relationships in Core Data - objective-c

I'm just starting out with using Core Data on the iPhone SDK and I'm looking into saving an ordered list, something like an array. However, relationships in Core Data are expressed as Sets when retrieved. This makes it difficult to save the order in which the objects are positioned.
A good example would be data items in table view when re-ordering of items are allowed. An easy solution would be to include an index property on the managed object.
Consider the following hierarchy:
Document <-Many-to-many-> DataItem
Different Document instances could link to the same DataItem, and each Document might reference one or more DataItem(s). Hence, having an index property in DataItem would lead to less reusability of that instance, i.e. you can only save the index for one instance of Document.
Any ideas of how I can present the hierarchy neatly ordered in a table view but still keep each DataItem instance reusable? Thanks!

As of OS X Lion (10.7) this is now much more straight forward. Cocoa now has support for a new NSOrderedSet class which is compatible with Core Data. This functionality is also available in iOS though requires iOS 5.0 or later. This means that this can't be used if you want your app to be backwards compatible with earlier versions of iOS or OS X.
All you need to do to gain ordering is open the Core Data model editor, select a to-many relationship and check the "ordered" check-box.

You could do it with another entity, like this:
alt text http://gallery.me.com/davedelong/100084/Screenshot-20on-202009-07-04-20at-2010-34-56-20AM/web.jpg?ver=12467253090001
A Document could find its actual dataItems by using something like this:
NSSet * documentDataItems = [[document orderedDataItems] valueForKey:#"dataItem"];
Likewise, a DataItem could find all its documents by doing the same:
NSSet * dataItemDocuments = [[dataItem orderedPositions] valueForKey:#"document"];

A good solution is to keep a separate data structure in Document to map DataItems to a position in the table view. Besides allowing the same DataItem to exist in multiple positions, if you need to add a DataItem to multiple Documents this solution will also work.
Back when I was looking at different strategies of keeping Core Data objects ordered I found a blog post that explains how to do this in great detail, including sample code too.

Related

How to store a List or Collection in a dataset table/column? (VB.NET)

I have a dataset table with various columns that are created during form load.
These columns are currently either system.double or system.string types.
And it is displayed in a datagridview.
This works fine.
But I need another column that can store a "list" or some collection in the data table.
A list of strings would do but a custom class would be better.
How is this usually done?
I have spent literally weeks googling this and I dont know where to start. The more I have looked the more confused I have ended up. I end up with more questions than answers, like how is it displayed in the datagridview? I read about a combo box?
I hope someone can give me some pointers in how to get this achieved. I've not posted any code as I think its more the theory of this I need help with.
What you are asking for has does have multiple concerns for most programmers. The storage of data (#1) and the displaying of said data to the user (#2)
For #1 I recommend the .net entity framework. It gives support for storing, querying and updating classes for use in the database. Through most tutorials that I have found it is possible to model the structure of the database tables and their relations and then build a database around that model OR to use an existing database and create entities (entity framework's class objects) around the existing structures and relationships.
Here is a link to a very good beginner tutorial that I have used before: CodeProject Entity Framework Tutorial for Absolute Beginners
For #2 I can recommend the Windows Presentation Foundation. It has lots of bells and whistles to make using a data source and displaying the relevant dependent data very easily through its unique method of data binding. From the tutorials I have used on PluralSight it can be as easy as dragging and dropping from an imported data source like the entity framework database. Alternatively, one can just handle selected row changes for one data grid and then show the dependent data in another data grid.

Use a 3rd party object as a Core Data Entity

I am wanting to pull down and cache notes, notebooks and tags from the Evernote service using their iOS SDK. Their SDK comes with a Store that returns an array of model objects matching a filtered criteria I set.
I want to take those models and use them as a Entity in Core Data. I understand that I can't, because they inherit from NSObject. So my question to all of you is what are the best practices I can employe when I model my entities based on the Evernote model objects? It is a real pain because every time they change something, I have to reflect the same changes in my entities. Is there a work around, or am I stuck building a bridge (so to speak)?.
Thanks,
Johnathon
Following my comment
I don't understand your question here. Just kick off a data import
each time models are returned from Evernote. Each model should be
designed through a Core Data entity.
and you reply on it.
Sorry, I'm not sure what you mean by importing. Bring down the objects
from Evernote then manually assign their object properties to my
entities? That will be a pain but is an option. There's a lot if
properties to copy.
With importing I mean that you should insert a managed object for each model returned from the results received data from Evernote.
This means that if Evernote returns a model that contains three properties, you shoul create an Entity that looks the same (or similar since it strictly depends on what you UI will be).
Here I suppose that you Core Data store is a cache. So you should apply synchronization stuff. Items should be inserted, updated or removed based on user. Synchronization is not easy to achieve but I can suggest you the following tutorials.
How To Synchronize Core Data with a Web Service – Part 1
How To Synchronize Core Data with a Web Service – Part 2
You could also take advantage of RestKit in this case, since it offers an integration with Core Data. In particular, it allows to maps NSObjects, for example returned from a JSON call, to a Core Data entity in a easy way. An example can be found at NSScrencast GitHub Repository. Note that I don't know how Evernote SDK works. So, this approach could not be useful.
But if you are new to RestKit and Core Data, I really suggest to stick with plain Core Data. It's already difficult as its own.
If you need something else let me know.
Update 1
I am going to be doing a synchronization for sure, so I assume I have
to map the Evernote object completely with a Managed Object. Since the
Evernote objects can contain data blobs representing video, pictures,
files etc, I will need to look at how to store that data in Core Data
as well.
In Core Data you need (this not a must but I really good advice) to store files (e.g. images) in the file system. Within an entity you should maintain only meta-informations (i.e. the path) of an image and through it retrieve the image later. This is not necessary for small data, but I think your binaries will be big in size.
Starting from iOS 5 there is a new flag called External Storage that do this for you based on heuristic algorithm.
If you specify that the value of a managed object attribute may be
stored as an external record, Core Data heuristically decides on a
per-value basis whether it should save the data directly in the
database or store a URI to a separate file that it manages for you.
About searching for binary file I really suggest to an attribute called, for example, tag. This will allow you to search images, videos, etc. Obviously when you save you need to associate that tag with the specified binary data. This is just an idea.
P.S. If you need further support I really suggest to open a new question on SO. This to have a self-contained question.
You probably wanna save the object as NSData. Since I don't know what object you're looking for to use, I can't really tell if it's suitable for this. To see if it is, you would have to check if the class adopts the NSCoding protocol.
More info on archiving could be found in Apple's documentation:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Archiving/Archiving.html

Accessing Stored Core Data Entities from Different Classes

I am quite new to Core Data, and I'm trying to implement it into my relatively simple OS X application. My application takes some file URLs provided by the user, gets some more information about the files (like creation date, for example), and then stores the URLs for use later.
I am wanting to have those file URLs, and related data, stored in a 'central' location so I can access, modify, and change the order of them (order is really important) from any of the classes in my application (correct me if I'm wrong, but I think Core Data is ideal for this).
I have my Core Data Model setup in Xcode (it only has one Entity which has a couple of Attributes), I've create an NSManagedObject Subclass to match the Entity in the Model, and I'm using Bindings to tie the data to a TableView. However, like I said, I need to be able get at this data from any class in my application. I have been reading Apple's Documentation and a book with a section on Core Data, however I am both struggling to get my head around it, and am yet to come across a section that describes the needs I mentioned above.
Any help with this (even just a link to a useful article) would be very much appreciated.
Thanks in advance.

What does the `ordered` flag do in a to-many relationship?

While looking for ways to add an ordered to-many relationship to my Core Data model, with the least possible amount of changes to the model, I noticed an option of the to-many relationship that says ordered (see screenshot below). Wow, sounds great, but what does it do?
My SQLite store is not complaining when I check or uncheck it, and my app still compiles and runs fine too. I was thinking maybe the lightweight migration takes care of the change, but from the looks of it, all my custom NSManagedObject subclasses work without the need for modification too, so what's going on?
To summarize the questions:
Should that ordered flag change the to-many relationship's data type from NSSet to NSArray?
Or is it just that the order in which the set is modified, will persist on sequential reads and writes?
Or am I wrong with my assumptions and is it something else entirely?
Is there an Apple doc page where this feature is described?
Many thanks!
Ordered relationships allow you to assign an arbitrary ordering to related objects. You can think of this as ordering colors from your most to least favorite, rather than sorting by date, title, etc.
Before this feature was added ordering was implemented by creating a position attribute, then manually updating the position indexes for items whenever the user reordered them. If you have a large number of items, using the built in ordering can be more expensive than implementing this manually, as described above.

Can i get/set the index generated by checking the 'indexed' checkbox? (core data)

I have 2 entities. entity A will hold many entity Bs and order will matter.
if i check the little box that says 'indexed' in xcode, how do i go about using that index, if i even can? ( i know that i CAN use it in some way: http://cocoawithlove.com/2008/03/testing-core-data-with-very-big.html but i am not so spiffy with Obj-c yet.)
I have seen this Indexed Relationships in Core Data , but it seems broken and too much over my head to fix myself.
Index doesn't mean what you think it means. In this context, "indexed" means like the index of a book. It add a lookup table so the database can find individual records quickly. If you need to be able to sort the records into a specific order, use NSSortDescriptor with the NSFetchRequest. If the existing properties are not what you want to sort on, you'll need to add another property.