iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) (99 page)

Read iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) Online

Authors: Aaron Hillegass,Joe Conway

Tags: #COM051370, #Big Nerd Ranch Guides, #iPhone / iPad Programming

BOOK: iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides)
9.68Mb size Format: txt, pdf, ePub
For the More Curious: Automatic Caching and Cache.db

While in
Nerdfeed
’s sandbox, you may have noticed a file named
Cache.db
. This file contains data that resembles the XML and JSON returned from the RSS web services. iOS applications keep the data from web service requests here. When an HTTP request is made, the response from the server may tell the application,

This data will be good for a day, so don’t bother me again in the meantime.

An iOS application has built-in behavior to understand this response and to cache the data returned in the
Cache.db
file until it

expires.

 

Earlier in the chapter, when asking repeatedly for Apple’s top songs feed, you may have noticed that the repeated requests returned very quickly – even before we implemented caching of our own. This was automatic caching at work. Automatic caching is especially useful for loading web pages, and it is what makes
Safari
run reasonably fast even on an iOS device.

 

So why, then, did we write our own caching mechanism for the RSS feeds? For applications that interact with web services and present data in their own views, automatic caching is not useful for two reasons. The first is that you have no control over the
Cache.db
file and its caching process, like what data gets saved and for how long.

 

The other reason is that automatic caching stores all of the data from a web service request in the format in which it was delivered. Using this cached data, then, would be a step backward for us in
Nerdfeed
. For example, in retrieving the BNR form feed from the web server, we already parse a subset of XML into
RSSItem
instances from the response. So we’re better off caching data in
RSSItem
s for later retrieval than using the data in
Cache.db
, which we’d have to figure out how to read, load, and parse again from scratch.

 

It doesn’t usually harm anything to let an iOS application keep a cache even if you are keeping one of your own. Sometimes, though, it is a problem. This is the case when your application downloads large files, like images and PDFs. The application will not only save these big files to the filesystem, but it might also keep them in memory for a long time.

 

For example, if you created an application that downloads and renders PDFs, it might store those PDFs in its own cache and then render them. Rendering a PDF is really memory-intensive, and if the built-in cache is keeping another copy of the PDF file for itself, your application may run out of memory and be shut down.

 

Therefore, you may want to selectively cache data or just remove built-in caching altogether. To do this, you create a subclass of
NSURLCache
and override
storeCachedResponse:forRequest:
.

 
@implementation BNRURLCache
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse
                 forRequest:(NSURLRequest *)request
{
    // If the file isn't a pdf, store it as normal, otherwise, ignore it
    if (![[[request URL] pathExtension] isEqualToString:@"pdf"])
        [super storeCachedResponse:cachedResponse forRequest:request];
}
@end
 

If you wanted to entirely remove caching, you would override this same method and not enter any code in the body.

 

Then, when your application starts up, you tell
NSURLCache
that the default caching object is an instance of your subclass.

 
BNRURLCache *uc = [[BNRURLCache alloc] init];
[NSURLCache setSharedURLCache:uc];
 
30
iCloud

iCloud is a service that is available on every iOS device running iOS 5 or later. At its most basic level, iCloud is a mechanism for storing files

in the cloud,

i.e. one or many remote servers. iCloud ties the stored data to a particular user in individual iCloud accounts. When you purchase an iOS device, you set that device up with your iCloud account. If you own other devices, you can associate them with your account, too. The shared data in the iCloud is available only to the user logged into the device. If another user logs into the device (which is rare), access to the original user’s iCloud data is removed.

 

There are two big features of iOS that use iCloud – key-value storage and document storage.

 

Key-value storage allows an application to synchronize preferences-like data across devices. For example, an application that allowed you to read books from a bookshelf might use this feature. You could begin reading a book on your iPad. If you later opened this application on your iPhone, it would open directly to the same book right where you left off reading on your iPad. The current book and location would be the data stored in iCloud. This type of data is stored and retrieved using the class
NSUbiquitousKeyValueStore
, which works much like
NSUserDefaults
.

 

Document storage lets you manage individual documents across the user’s devices. For example, an application might allow you to create and edit spreadsheets. You could create a spreadsheet on an iPhone and then edit it on an iPad. When you next opened the spreadsheet on the iPhone, the changes from the iPad would be there. This feature is exposed through the classes
UIDocument
,
NSFileCoordinator
,
NSMetadataQuery
, and the protocol
NSFilePresenter
.

 

Core Data leverages iCloud’s document storage to synchronize a Core Data SQLite file across a number of iOS devices. In this chapter, you will synchronize the read list for
Nerdfeed
across all of the user’s devices using Core Data’s built-in iCloud behavior.

 
iCloud Requirements

The code you will write in this chapter is relatively straightforward, but there are some things you need to do first to be able to write that code.

 
  • You must have a device to run
    Nerdfeed
    on; iCloud doesn’t work on the simulator. In fact, you really need
    two
    iOS devices to realistically test if the read list has been shared correctly between devices.
 
  • You must be an administrator or team agent in Apple’s iOS Developer Program to create the provisioning profile required for iCloud use. (We’ll set up this provisioning profile in a moment.)
 
  • You must have an iCloud account set up and have iCloud enabled on your test devices. To see how to set up your iCloud account, visit
    http://www.apple.com/icloud/setup/
    . To enable iCloud on a device, go to the
    Settings
    , select
    iCloud
    , and follow the instructions.
 

Make sure you have met these requirements before continuing. If not, the changes you are about to make to
Nerdfeed
will no longer allow it to run on your device.

 
Ubiquity Containers

Now on to the fun stuff. So far, you know that every file that an application saves and loads is within the application’s sandbox. These files are only available to the application that owns the sandbox, and they only exist on the device on which they were created. iCloud changes this situation with special directories called
ubiquity containers
.

 

You can think of a ubiquity container as a folder that lives on Apple’s iCloud servers. An iOS device keeps a local copy of the ubiquity container on its filesystem. When an iOS device makes changes to the files in its local copy, those changes are automatically uploaded to the actual ubiquity container in the cloud. Any other device that has access to that ubiquity container then transfers the changes to its local copy (
Figure 30.1
).

 

Figure 30.1  Ubiquity containers

 

A ubiquity container has a unique identifier called a
container identifier string
. If an application knows the identifier string for a ubiquity container, then it has access to the files within it. To give an application access to the ubiquity container, you add the container identifier string to the list of
entitlements
for the application.

 

In the project navigator, select the
Nerdfeed
project and then the
Summary
tab for the
Nerdfeed
target. Find the
Entitlements
section and check the
Enable Entitlements
box on (
Figure 30.2
).

 

Figure 30.2  Turning on iCloud entitlements

 

Checking this box on turns on entitlements for
Nerdfeed
. An entitlement is essentially permission to access a secure resource, like a ubiquity container or the device’s encrypted keychain.

 

By default, turning on entitlements gives the application access to a ubiquity container with an identifier string that is the same as the application’s bundle (as shown in the
iCloud Containers
table in
Figure 30.2
). Thus,
Nerdfeed
now has access to the
com.bignerdranch.Nerdfeed
ubiquity container in iCloud.

 

Giving an application access to a ubiquity container has two purposes. First, ubiquity containers allow an application to share data with other applications. This is often used for a suite of applications developed by the same company. For example, an application that created presentations could access the ubiquity container for an application that created spreadsheets, and the spreadsheet could be imported into the presentation. Better yet, because multiple devices can run the same application, the spreadsheet could even be created on a different device than the presentation.

 

The other purpose of ubiquity containers is to give all of the user’s devices that an application runs on access to the same set of data. Thus, if a user has an iPad and an iPhone, the
Nerdfeed
application can access the same ubiquity container on both devices. (Remember the ubiquity container is unique to the logged in iCloud user – you can only share between devices that have the same iCloud account.)

 

Nerdfeed
will store its Core Data information (the list of read item URLs) in the
com.bignerdranch.Nerdfeed
ubiquity container. When this application is run on multiple devices, the same information will be available on all of them. Then users will be able to keep track of which items they have read no matter what device they are using
Nerdfeed
on.

 

Other books

Miles From Home by Ava Bell
Football Frenzy by Alex Ko
The Academy: Book 1 by Leito, Chad
Beloved by Annette Chaudet
Contract With God by Juan Gomez-Jurado
Eric S. Brown by Last Stand in a Dead Land
Cuckoo Song by Frances Hardinge