Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Beginning iOS5 Development.pdf
Скачиваний:
7
Добавлен:
09.05.2015
Размер:
15.6 Mб
Скачать

CHAPTER 13: Basic Data Persistence

475

Figure 13–6. Our project template with the files needed for Core Data. The Core Data model is selected, and the data model editor is shown in the editing pane.

Entities and Managed Objects

Most of what you see in the project navigator should be familiar: the application delegate and the various files in the Supporting Files folder. In addition, you’ll find a file called Core_Data_Persistence.xcdatamodeld, which contains our data model. Within Xcode, Core Data lets us design our data models visually, without writing code, and stores that data model in the .xcdatamodeld file.

Single-click the .xcdatamodeld file now, and you will be presented with the data model editor (see the right side of Figure 13–6). The data model editor gives you two distinct views into your data model, depending on the setting of the control in the lower-right corner of the project window. In Table mode, the mode shown in Figure 13–6, the elements that make up your data model will be shown in a series of editable tables. In Graph mode, you’ll see a graphical depiction of the same elements. At the moment, both views reflect the same, empty data model.

Before Core Data, the traditional way to create data models was to create subclasses of NSObject and conform them to NSCoding and NSCopying so that they could be archived, as we did earlier in this chapter. Core Data uses a fundamentally different approach. Instead of classes, you create entities here in the data model editor, and then in your code, you create managed objects from those entities.

www.it-ebooks.info

476

CHAPTER 13: Basic Data Persistence

NOTE: The terms entity and managed object can be a little confusing, since both refer to data model objects. Entity refers to the description of an object. Managed object refers to actual concrete instances of that entity created at runtime. So, in the data model editor, you create entities, but in your code, you create and retrieve managed objects. The distinction between entities and managed objects is similar to the distinction between a class and instances of that class.

An entity is made up of properties. There are three types of properties:

Attributes: An attribute serves the same function in a Core Data entity as an instance variable does in an Objective-C class. They both hold the data.

Relationships: As the name implies, a relationship defines the relationship between entities. For example, to create a Person entity, you might start by defining a few attributes, like hairColor, eyeColor, height, and weight. You might define address attributes, like state and ZIP code, or you might embed those in a separate, HomeAddress entity. Using the latter approach, you would then create a relationship between a Person and a HomeAddress. Relationships can be to-one and to-many. The relationship from Person to HomeAddress is probably to-one, since most people have only a single home address. The relationship from HomeAddress to Person might be to-many, since there may be more than one Person living at that HomeAddress.

Fetched properties: A fetched property is an alternative to a relationship. Fetched properties allow you to create a query that is evaluated at fetch time to see which objects belong to the relationship. To extend our earlier example, a Person object could have a fetched property called Neighbors that finds all HomeAddress objects in the data store that have the same ZIP code as the Person’s own HomeAddress. Due to the nature of how fetched properties are constructed and used, they are always one-way relationships. Fetched properties are also the only kind of relationship that lets you traverse multiple data stores.

Typically, attributes, relationships, and fetched properties are defined using Xcode’s data model editor. In our Core Data Persistence application, we’ll build a simple entity so you can get a sense of how this all works together.

Key-Value Coding

In your code, instead of using accessors and mutators, you will use key-value coding to set properties or retrieve their existing values. Key-value coding may sound intimidating, but you’ve already used it quite a bit in this book. Every time we used NSDictionary, for example, we were using key-value coding, because every object in a

www.it-ebooks.info

CHAPTER 13: Basic Data Persistence

477

dictionary is stored under a unique key value. The key-value coding used by Core Data is a bit more complex than that used by NSDictionary, but the basic concept is the same.

When working with a managed object, the key you will use to set or retrieve a property’s value is the name of the attribute you wish to set. So, here’s how to retrieve the value stored in the attribute called name from a managed object:

NSString *name = [myManagedObject valueForKey:@"name"];

Similarly, to set a new value for a managed object’s property, do this:

[myManagedObject setValue:@"Gregor Overlander" forKey:@"name"];

Putting It All in Context

So, where do these managed objects live? They live in something called a persistent store, also referred to as a backing store. Persistent stores can take several different forms. By default, a Core Data application implements a backing store as an SQLite database stored in the application’s Documents directory. Even though your data is stored via SQLite, classes in the Core Data framework do all the work associated with loading and saving your data. If you use Core Data, you don’t need to write any SQL statements. You just work with objects, and Core Data figures out what it needs to do behind the scenes.

SQLite isn’t the only option Core Data has for storage. Backing stores can also be implemented as binary flat files, or even stored in an XML format. Another option is to create an in-memory store, which you might use if you’re writing a caching mechanism, but it doesn’t save data beyond the end of the current session. In almost all situations, you should just leave it as the default and use SQLite as your persistent store.

Although most applications will have only one persistent store, it is possible to have multiple persistent stores within the same application. If you’re curious about how the backing store is created and configured, take a look at the file BIDAppDelegate.m in your Xcode project. The Xcode project template we chose provided us with all the code needed to set up a single persistent store for our application.

Other than creating it (which is handled for you in your application delegate), you generally won’t work with your persistent store directly, but rather will use something called a managed object context, often referred to as just a context. The context manages access to the persistent store and maintains information about which properties have changed since the last time an object was saved. The context also registers all changes with the undo manager, meaning that you always have the ability to undo a single change or roll back all the way to the last time data was saved.

NOTE: You can have multiple contexts pointing to the same persistent store, though most iOS applications will use only one. You can find out more about using multiple contexts and the undo

manager in the Apress book More iOS 5 Development.

www.it-ebooks.info

478

CHAPTER 13: Basic Data Persistence

Many Core Data method calls require an NSManagedObjectContext as a parameter or must be executed against a context. With the exception of very complicated, multithreaded iOS applications, you can just use the managedObjectContext property provided by your application delegate, which is a default context that is created for you automatically, also courtesy of the Xcode project template.

You may notice that, in addition to a managed object context and a persistent store coordinator, the provided application delegate also contains an instance of NSManagedObjectModel. This class is responsible for loading and representing, at runtime, the data model you will create using the data model editor in Xcode. You generally won’t need to interact directly with this class. It’s used behind the scenes by the other Core Data classes so they can identify which entities and properties you’ve defined in your data model. As long as you create your data model using the provided file, there’s no need to worry about this class at all.

Creating New Managed Objects

Creating a new instance of a managed object is pretty easy, though not quite as straightforward as creating a normal object instance using alloc and init. Instead, you use the insertNewObjectForEntityForName:inManagedObjectContext: factory method in a class called NSEntityDescription. NSEntityDescription’s job is to keep track of all the entities defined in the app’s data model. This method returns an instance representing a single entity in memory. It returns either an instance of NSManagedObject that is set up with the correct properties for that particular entity or, if you’ve configured your entity to be implemented with a specific subclass of NSManagedObject, an instance of that class. Remember that entities are like classes. An entity is a description of an object and defines which properties a particular entity has.

To create a new object, do this:

theLine = [NSEntityDescription insertNewObjectForEntityForName:@"EntityName"

inManagedObjectContext:context];

The method is called insertNewObjectForEntityForName:inManagedObjectContext: because, in addition to creating the object, it inserts the newly created object into the context and then returns that object. After this call, the object exists in the context but is not yet part of the persistent store. The object will be added to the persistent store the next time the managed object context’s save: method is called.

Retrieving Managed Objects

To retrieve managed objects from the persistent store, you’ll make use of a fetch request, which is Core Data’s way of handling a predefined query. For example, you might say, “Give me every Person whose eyeColor is blue.”

After first creating a fetch request, you provide it with an NSEntityDescription that specifies the entity of the object or objects you wish to retrieve. Here is an example that creates a fetch request:

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]