Home > Articles > Operating Systems, Server

This chapter is from the book

The Core Data Approach

Core Data, on the other hand, combines all the speed and efficiency of database storage with the object-oriented goodness of object serialization.

Entities and Managed Objects

When you create your model objects, instead of starting out by writing the .h @interface for the class, you typically begin by modeling your entities, using the Xcode Data Modeler. An entity corresponds to one type of object, such as a Patient or Doctor object, and sets out the attributes for that entity, such as firstName and lastName. You use the data modeler to set which attributes will be persisted to disk, along with various other features such as the type of data that an attribute will hold, data validation requirements, or whether an attribute is optional or required.

When you work with actual instances of model objects, such as a specific Patient object, you're dealing with an instance of a managed object. These objects will either be instances of the NSManagedObject class, or a custom subclass of NSManagedObject. If you don't specify a custom subclass in the modeler, you would typically access the attributes of the object through Key Value Coding (KVC), using code like that in Listing 2.1.

Listing 2.1. Accessing the attributes of a managed object

NSManagedObject *aPatientObject; // Assuming this has already been fetched

NSString *firstName = [aPatientObject valueForKey:@"firstName"];
NSString *lastName = [aPatientObject valueForKey:@"lastName"];

[aPatientObject setValue:@"Pain killers" forKey:@"currentMedication"];
[aPatientObject setValue:@"Headache" forKey:@"currentIllness"];

If you choose to do so, you can also provide your own subclass of NSManagedObject, to expose accessor methods and/or properties for your managed object, so you could use the code shown in Listing 2.2. You'll look at this in more detail in Chapter 6, "Working with Managed Objects."

Listing 2.2. Using a custom subclass of NSManagedObject

Patient *aPatientObject; // Assuming this has already been fetched

NSString *firstName = [aPatientObject firstName];
NSString *lastName = aPatientObject.lastName;

[aPatientObject setCurrentMedication:@"Pain killers"];
aPatientObject.currentIllness = @"Headache";

You could also still access the values of the object using valueForKey:, etc., if you wish.

Relationships

The Data Modeler is also the place where you define the relationships between your entities. As an example, a Patient object would have a relationship to a Doctor, and the Doctor would have a relationship to the Patient, as shown in Figure 2.1.

Figure 2.1

Figure 2.1 A Patient-Doctor relationship

When modeling relationships, you typically think in relational database terms, such as one-to-one, one-to-many, and many-to-many. In the example shown in Figure 2.1, a patient has only one doctor, but a doctor has many patients, so the doctor-patient relationship is one-to-many.

If the doctor-patient relationship is one-to-many, the inverse relationship (patient-doctor) is obviously many-to-one. When you model these relationships in the Data Modeler, you need to model them both, explicitly, and set one as the inverse of the other. By setting the inverse relationship explicitly, Core Data ensures the integrity of your data is automatically maintained; if you set a patient to have a particular doctor, the patient will also be added to the doctor's list of patients without you having to do it yourself.

You specify a name for each relationship, so that they are exposed in a similar way to an entity's attributes. Again, you can either work with KVC methods, or provide your own accessors and property declarations in a custom subclass, using code like that in Listing 2.3.

Listing 2.3. Working with relationships

Patient *aPatientObject; // Assuming this has already been fetched
Doctor *aDoctorObject = [aPatientObject valueForKey:@"doctor"];

Patient *anotherPatientObject; // also already fetched
anotherPatientObject.doctor = aDoctorObject;
   // The inverse relationship is automatically set too

NSLog(@"Doctor's patients = %@", [aDoctorObject patients]);
/* Outputs:
      Doctor's patients = (
                             aPatientObject,
                             anotherPatientObject,
                             etc...
                          )

   */

It's important to note that Core Data doesn't maintain any order in collections of objects, including to-many relationships. You'll see later in the book how objects probably won't be returned to you in the order in which you input them. If order is important, you'll need to keep track of it yourself, perhaps using an ascending numerical index property for each object.

If you're used to working with databases such as MySQL, PostgreSQL, or MS SQL Server (maybe with web-based applications in Ruby/Rails, PHP, ASP.NET, etc.), you're probably used to every record in the database having a unique id of some sort. When you work with Core Data, you don't need to model any kind of unique identifier, nor do you have to deal with join tables between related records. Core Data handles this in the background; all you have to do is to define the relationships between objects, and the framework will decide how best to generate the underlying mechanisms, behind the scenes.

Managed Object Contexts

So far, the code in this chapter has assumed that you've fetched an object "from somewhere." When you're working with managed objects and Core Data, you're working within a certain context, known as the Managed Object Context. This context keeps track of the persistent storage of your data on disk (which on iOS is probably a SQLite store) and acts as a kind of container for the objects that you work with.

Conceptually, it's a bit like working with a document object in a desktop application—the document represents the data stored on disk. It loads the data from disk when a document is opened, perhaps allowing you to display the contents in a window on screen. It keeps track of changes to the document, likely holding them in memory, and is then responsible for writing those changes to disk when it's time to save the data.

The Managed Object Context (MOC) works in a similar way. It is responsible for fetching the data from the store when needed, keeping track of the changes made to objects in memory, and then writing those changes back to disk when told to save. Unless you specifically tell the MOC to save, any changes you make to any managed objects in that context will be temporary, and won't affect the underlying data on disk.

Unlike a normal document object, however, you are able to work with more than one managed object context at a time, even though they all relate to the same underlying data. You might, for example, load the same patient object into two different contexts, and make changes to the patient in one of the contexts (as shown in Figure 2.2). The object in the other context would be unaffected by these changes, unless you chose to save the first context. At that point, a notification would be sent to inform you that another context had changed the data, and you could reload the second context if you wanted to.

Figure 2.2

Figure 2.2 Managed Object Contexts and their Managed Objects

Although it's less common to work with multiple contexts on iOS than it is on the desktop, you typically use a separate context if you're working with objects in the background, such as pulling information from an online source and saving it into your local app's data. If you choose to use the automatic Undo handling offered by managed object contexts, you might set up a second context to work with an individual object, handling undo for any changes to individual attributes as separate actions. When it was time to save that object back into your primary context, the act of saving all those changes would count as one undo action in the primary context, allowing the user to undo all the changes in one go if they wanted to. You'll see examples of this in later chapters.

Fetching Objects

The managed object context is also the medium through which you fetch objects from disk, using NSFetchRequest objects. A fetch request has at minimum the name of an entity; if you wanted to fetch all the patient records from the persistent store, you would create a fetch request object, specify the Patient entity to be retrieved, and tell the MOC to execute that fetch request. The MOC returns the results back to you as an array. Again, it's important to note that the order in that array probably won't be the same as the order in which you stored the objects, or the same as the next time you execute the fetch request, unless you request the results to be sorted in a particular order.

To fetch specific objects, or objects that match certain criteria, you can specify a fetch predicate; to sort the results in a certain order, you can provide an array of sort descriptors. You might choose to fetch all the patient records for a particular doctor, sorting them by last name. Or, if you had previously stored a numerical index on each patient as they were stored, you could ask for the results to be sorted by that index so that they would be returned to you in the same order each time.

Faulting and Uniquing

Core Data also works hard to optimize performance and keep memory usage to a minimum, using a technique called faulting.

Consider what could happen if you loaded a Patient record into memory; in order that you have access to that patient's Doctor object, it might seem that you'd want to have the Doctor object loaded as well. And, since you might need to access the other patients related to that doctor, you should probably load all those Patient objects too. With this behavior, what you thought was a single-object fetch could turn into a fetch of thousands of objects—every related object would need to be fetched, possibly resulting in fetching your entire dataset.

To solve this problem, Core Data doesn't fetch all the relationships on an object. It simply returns you the managed object that you asked for, with the relationships set to faults. If you try and access one of those relationships, such as asking for the name of the patient's doctor, the "fault will fire" and Core Data will fetch the requested object for you. And, as before, the relationships on a newly fetched doctor object will also be set to faults, ready to fire when you need to access any of the related objects. All of this happens automatically, without you needing to worry about it.

A managed object context will also ensure that if an object has already been loaded, it will always return the existing instance in any subsequent fetches. Consider the code in Listing 2.4.

Listing 2.4. Fetching unique objects

Patient *firstPatient; // From one fetch request
Doctor *firstPatientsDoctor = firstPatient.doctor;
Patient *secondPatient; // From a second fetch request
Doctor *secondPatientsDoctor = secondPatient.doctor;

/* If the two patients share the same doctor, then the doctor instance
   returned after each fault fires will be the same instance: */

if( firstPatientsDoctor == secondPatientsDoctor )
{
    NSLog(@"Patients share a doctor!");
}

This is known as uniquing—you will only ever be given one object instance in any managed object context for, say, a particular Patient.

Persistent Stores and Persistent Store Coordinators

The underlying data is held on disk in a persistent store. On an iOS device, this is usually a SQLite store. You can also choose to use a binary store or even your own custom atomic store type, but these require the entire object graph to be loaded into memory, which can quickly become a problem on a device with limited resources.

You never need to communicate directly with a persistent store, or worry about how it is storing data. Instead, you rely on the relationship between the managed object context and a persistent store coordinator.

The persistent store coordinator acts as a mediator to the managed object contexts; it's also possible to have a coordinator talk to multiple persistent stores on disk, meaning that the coordinator would expose the union of those stores to be accessed by the managed object contexts.

You won't typically need to worry too much about persistent stores and coordinators unless you want to work with multiple stores or define your own store type. In the next section, you'll see the code from the Xcode template project that sets up the persistent store for you. Once this is dealt with, you'll spend most of your time concentrating on the managed objects, held within managed object contexts.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020