CHAPTER 7

image

Storing and Sharing Data

The Apple TV has undergone quite an evolution when it comes to storage. The original Apple TV came with a standard 40GB or 160GB hard drive. The Apple TV would use that storage for holding movies, TV shows, and music locally on the Apple TV. For the next two generations of the Apple TV, Apple removed the hard drive completely. Instead, the Apple TV was equipped with 8GB of flash storage. These boxes lacked the ability to locally store any media; instead movies, TV shows, and music all had to be streamed either from a local computer or across the Internet. With the fourth-generation, Apple has released a hybrid solution. The new Apple TVs come in either 32GB or 64GB versions, but apps are still required to stream most of their data and content. Apple currently limits an app to a total of 200MB of local storage, but this data are temporary and can be removed when the app is quit.

This chapter will discuss methods for storing information locally on the Apple TV, as well as how to sync data using iCloud.

Preferences

There are some things to consider when deciding where to store certain kinds of information. The easiest way to store information is within the preferences file, but this method has some downsides.

All of the data are both read and written at the same time. If you are going to be writing often or writing large amounts of data, this could take time and slow down your application. As a general rule, your preferences file should never be larger than 100KB. Currently, the preference file is capped at 500KB for tvOS, but a developer should consider other storage methods long before reaching that limit.

The preferences file is really nothing more than a standardized file with accompanying classes and methods to store application-specific information. A preference would be, for example, the sorting column and direction (ascending/descending) of a list. Anything that is generally customizable within an app should be stored in its preferences file.

Writing Preferences

Apple has provided developers with the NSUserDefaults class; this class makes it easy to read and write preferences for the iPhone, AppleTV, and Mac OS X. The great thing is that, in this case, you can use the same code for iOS and Mac OS X. The only difference between the two implementations is the location of the preferences file.

All you need to do to write preferences is to create an NSUserDefaults object. This is done with the following code:

let prefs: NSUserDefaults = NSUserDefaults.standardUserDefaults()

This instantiates the prefs object so you can use it to set preference values. Next, you need to set the preference keys for the values that you want to save. The BookStore app example will be used to demonstrate specific instructions throughout this chapter. When running a bookstore, you might want to save a username or password in the preferences. You also might want to save things such as a default book category or recent searches. The preferences file is a great place to store this type of information because this is the kind of information that needs to be read only when the application is launched.

Also, on tvOS, it is often necessary to save your current state. If a person is using your application presses the home button, you want to be able to bring them back to the exact place they were in your application when they are done with their phone call.

Once you have instantiated the object, you can just call setObjectforKey to save your preferences. If you wanted to save the username of sherlock.holmes, you would call the following line of code:

prefs.setObject("sherlock.holmes", forKey: "username")

You can use setInteger, setDouble, setBool, setFloat, and setURL instead of setObject, depending on the type of information you are storing in the preferences file. Let’s say you store the number of books a user wants to see in the list. Here is an example of using setInteger to store this preference:

prefs.setInteger(10, forKey:"booksInList")

After a certain period of time, your app will automatically write changes to the preferences file.

With just three lines of code, you are able to create a preference object, set two preference values, and write the preferences file. It is an easy and clean process. Here is all of the code:

let prefs: NSUserDefaults = NSUserDefaults.standardUserDefaults()
prefs.setObject("sherlock.holmes", forKey: "username")
prefs.setInteger(10, forKey:"booksInList")

Reading Preferences

Reading preferences is similar to writing preferences. Just like with writing, the first step is to obtain the NSUserDefaults object. This is done in the same way as it was done in the writing process:

let prefs: NSUserDefaults = NSUserDefaults.standardUserDefaults()

Now that you have the object, you are able to access the preference values that are set. For writing, you use the setObject syntax; for reading, you use the stringForKey method. You can use the stringForKey method because the value you put in the preference was a String. In the writing example, you set preferences for the username and for the number of books in the list to display. You can read those preferences by using the following simple lines of code:

var username = prefs.stringForKey("username")
var booksInList = prefs.integerForKey("booksInList")

Pay close attention to what is happening in each of these lines. You start by declaring the variable username, which is a string. This variable will be used to store the preference value of the username you stored in the preferences. Then, you just assign it to the value of the preference username.

iCloud

The iCloud is a service provided by Apple that allows developers to sync data and information across multiple devices. This is especially helpful with tvOS apps since the local storage is limited. In order to implement iCloud storage in an app, a developer must first make sure that their app has iCloud enabled. To do this, visit the Apple Developer Portal (http://developer.apple.com). Sign in and click Member Center in the top right corner of the screen. Then click Certificates, Identifiers & Profiles, as shown in Figure 7-1.

9781484217146_Fig07-01.jpg

Figure 7-1. Selecting Certifications, Identifiers & Profiles

Next, select Identifiers under the iOS section. Then select App IDs from the left-hand side, as shown in Figure 7-2.

9781484217146_Fig07-02.jpg

Figure 7-2. Select App IDs

Find the App ID in the list and select it. This will bring up a list of the Application Services available in the app, as shown in Figure 7-3.

9781484217146_Fig07-03.jpg

Figure 7-3. Current App ID entitlement

Click the Edit button at the bottom of the list to add iCloud support. The check boxes seen in Figure 7-4 allow a developer to enable iCloud. Check the box and the app should now have access to iCloud.

9781484217146_Fig07-04.jpg

Figure 7-4. Enabling iCloud

It is also possible to add iCloud capabilities through Xcode. On the left-hand side, select your project, then select the active target, and choose the Capabilities tab. You will then see a screen similar to that shown in Figure 7-5.

9781484217146_Fig07-05.jpg

Figure 7-5. Adding iCloud capabilities through Xcode

You can turn iCloud on and off through this method also. Now with iCloud enabled, it is possible to easily store your data in the cloud.

iCloud KVS

There are two ways to store information in iCloud. One way is to implement iCloud KVS or key-value storage. The second way is by using CloudKit. CloudKit is more powerful and more complicated. It will be discussed in Chapter 8. iCloud KVS is very similar to NSUserDefaults and should only be used for storing very small amounts of data. Apple caps the iCloud KVS storage at 1MB. The major benefit to using iCloud KVS is that the data are automatically synced across all iCloud devices within the same account.

The iCloud KVS is implemented very similarly to NSUserDefaults. It has the same limitations and issues, but is also used in a very similar way. The code to implement iCloud KVS is fairly simple. Start by creating a new Xcode project. Make sure tvOS Application is selected. For this project, use Single View Application, as shown in Figure 7-6.

9781484217146_Fig07-06.jpg

Figure 7-6. Creating a new project

Click Next and enter the name and details of the app. We used the name iCloudStorage, as shown in Figure 7-7.

9781484217146_Fig07-07.jpg

Figure 7-7. Naming you project

Once the project save location is selected, Xcode will open the project. Select the AppDelegate.swift file from the left-hand side of the list of files. We will be implementing the iCloud KVS in the AppDelegate.swift file.

Image Note  In a real-world project, it is better to create a singleton manager to handle your data syncing. Singletons are classes that are only instantiated a single time. They are easier to extend and access. A singleton is implemented in Swift through the use of static class variables.

At the top of the AppDelegate class, under the window variable, you need to add the following two variables:

var iCloudKeyStore: NSUbiquitousKeyValueStore = NSUbiquitousKeyValueStore.defaultStore()
var iCloudString: String = String()

The first variable, iCloudKeyStore, is an NSUbiquitousKeyValueStore value. This basically means that it is like an NSUserDefaults that is stored in the cloud. The second variable, iCloudString, is a string that will be used to store the value synced through iCloud.

Next, you will modify the application:didFinishLaunchingWithOptions: method. You need to tell the iCloud service to alert you once your NSUbiquitousKeyValueStore is changed by another app. This way you can reload your iCloudString from the key store. Add the following lines:

NSNotificationCenter.defaultCenter().addObserver(self,
            selector: "iCloudDataChanged:",
            name:  NSUbiquitousKeyValueStoreDidChangeExternallyNotification,
            object: iCloudKeyStore)

This code tells the notification center to call the method "iCloudDataChanged:" on your AppDelegate object whenever your key store changes values in any way. Notice the iCloudKeyStore variable is passed in. It is possible to have multiple key stores and receive notifications for them separately. Next, you will add the code to check the key store for the string:

27    if let savedString = iCloudKeyStore.stringForKey("myString") {
28        iCloudString = savedString
29    } else {
30        iCloudKeyStore.setString("Testing", forKey: "myString")
31        iCloudKeyStore.synchronize()
32     }

Let’s walk through this code. The name of the key you are using in the NSUbiquitousKeyValueStore is myString. Obviously, when creating a real app, you will want to use descriptive titles for your keys such as username or default view. Line 27 attempts to set the value of savedString to the key myString from the key store. If this succeeds, that means the key exists. You then assign the value of savedString to the iCloudString variable.

If you are unable to pull myString from the key store, this means the key has yet to be set in the cloud. You then need to tell the key store to store a value for this key. Line 30 calls the method setString on the key store and passes in a String (Testing) and a key (myString). Line 31 then tells the key store to sync the data immediately with the cloud. By default, an NSUbiquitousKeyValueStore will sync its data on a regular basis, but by calling the synchronize method, you can force the sync immediately.

Image Note  In this example, you use setString and stringForKey to set and retrieve the string value from the key store. Apple provides different methods for different data types. The following retrieval methods are available:

- arrayForKey:
- boolForKey:
- dataForKey:
- dictionaryForKey:
- doubleForKey:
- longLongForKey:
- objectForKey:
- stringForKey:

The AppDelegate.swift file should now look like the one shown in Figure 7-8.

9781484217146_Fig07-08.jpg

Figure 7-8. AppDelegate.swift file

There is still one problem with our code. You have told the NSNotificationCenter to call the method iCloudDataChanged on your appdelegate, but this method has not yet been defined. Add the following method to the AppDelegate.swift file:

func iCloudDataChanged() {
    if let myString = iCloudKeyStore.stringForKey("myString") {
        iCloudString = myString
    }
}

This method merely assigns the value of myString from the key store to the iCloudString variable.

You can now compile and run your app.

Image Note  You may receive a console message at run time similar to the following error:

NSUbiquitousKeyValueStore error: com.innovativeware.iCloudStorage has no valid com.apple.developer.ubiquity-kvstore-identifier entitlement

This means you have not set up your entitlements for your app correctly.

Summary

In this chapter, you learned how to handle local storage on the Apple TV. You also learned how to add iCloud storage. We showed you how to become alerted to a change in the iCloud storage and how to send and receive values to and from it.

Exercises

  1. Add a number to your NSUbiquitousKeyValueStore.
  2. Add an Array to your cloud storage.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset