© Jesse Feiler 2019
Jesse FeilerImplementing iOS and macOS Documents with the Files Apphttps://doi.org/10.1007/978-1-4842-4492-0_9

9. Using User Defaults, Settings, and Preferences

Jesse Feiler1 
(1)
Plattsburgh, NY, USA
 

Documents are the primary way of saving data for apps. You can share the document with various apps and users so that the data is available to all users, but there are other ways to store and manage data in an app. Documents are the workhorses because you can control how much data is saved and how it is saved and shared.

Since the beginning of the iOS and macOS systems (and their predecessors) there has been another set of tools that let you store data. These tools are commonly used for user defaults, settings, and preferences. The data that they store and use is typically limited in size and scope. Even the terminology of these tools (user defaults, settings, and preferences) suggests the small size of the data involved. This remains true, but it is important to consider the fact that with the advances in technology, including data storage, user defaults, settings, and preferences, can in fact be a more central part of your app’s data strategy.

Note

Strictly speaking, a preference is the value of a setting such as the color to be used for drawing a new line where the value is blue for the lineColor preference. Once the value of a setting is set, it persists and is used each time the app runs until it is changed. In this case, the preference may be referred to as a default. In iOS, the built-in Settings app lets users control preferences and settings.

Preferences in Cocoa are stored in the Cocoa preferences system (also known as user defaults). If you want to make a strict distinction among these terms, in iOS the built-in Settings app controls these values for users. In Cocoa and Cocoa Touch, the user defaults system manages a database with the values. Some people distinguish between settings (part of the user interface) and user defaults (part of the Cocoa frameworks).

This chapter explores the possibilities you can use today for these data tools.

Looking at the Data Structures

When you are working with documents, you can control the formatting and management of the data. You can use a standard document type, which may have associated classes (images, for example), but the data for user defaults, settings, and preferences is more limited. Specifically, these objects must all be property list elements. A property list is a key-value structure where the keys are strings and the values are any of the following simple data types:
  • String

  • Date

  • Integer number

  • Float number

  • Boolean

A property list (extension .plist) is designed for efficient serialization. The PropertyListSerialization class handles this for you. Property lists are used throughout Cocoa; over the years, this code has been refined and tested so that it can be relied on for many tasks.

In addition, a NSData type can be stored in a property list. If you do this, you must handle the serialization and deserialization of that data to or from an object that you want to deal with. A very common case is converting a NSData type to some binary format, which can then be interpreted as an image or other complex data structure.

Property lists can also include arrays and dictionaries. This means that you can use a property list, which itself is an array containing a dictionary that also declares another array as well as numbers and other simple objects.

The other constraint to bear in mind when considering user defaults, settings, and preferences is that the guidance from Apple is that these tools should be used only for limited purposes and relatively small amounts of data.

When thinking about storing data in this way, don’t worry too much about how much data can be stored as user defaults, settings, or preferences because that’s not really the limiting factor. If you use up almost all of a device’s storage in this way, you will degrade performance long before you run out of space.

Property lists are stored as instances of the PropertyListSerialization class. As instances of this class, property lists are read and written in full when they are read or written. This can mean that in order to access a single Boolean value, you may need to read or write an entire property list with dozens, hundreds, or even thousands of items. You can focus your reading or writing by storing property list values in an array or dictionary, but this doesn’t really help you much. You will need to read the entire property list in order to get to the array or dictionary and only then will you be able to hone in on the value you want.

The data that is stored as defaults, preferences, and settings can be anything that you want to store (provided that it is a property list and doesn’t take up too much space). There is a difference between these terms and this is a good place to start to understand them.

Exploring User Defaults, Preferences, and Settings

All of these data structures can be stored in property lists, but understanding how they are used can help you use them most efficiently. Remember that these structures are always stored in property lists, which means they are stored in key-value structures. For that reason, each user default, preference, and setting has a name (the key under which it is stored). There may be other data stored under that key—perhaps a lot of it—but each has a key.

Tip

When you are thinking about using these tools to store your own data, remember that the Settings app and user defaults system manage the data. If you want total control over the data, how it is stored, and the user interface for it, you may want to use a database or document where you control these features.

Understanding User Defaults

A user default value is a starting value (default) for some aspect of your app. For example, an app that lets you store the names of students in a class may start by identifying students as Student 1, Student 2, and so forth. A new student that a user adds might be called New Student.

In an app like this, you might want to let the users set their own defaults such as these:
  • “Student” is the name of each item in the app and new items are labelled “New Student.”

  • You could change the default value for items to be “Item” so that you would have “Chair” and “New Chair” as the app runs.

  • A slightly more complex default might let a user choose between “New” and a number to identify a new item, as in New Chair or Chair 3.

Defaults like this are often exposed to the user so that they can choose.

Tip

In a case like this, an empty string may be the default.

Exploring Settings

There is a user defaults database that stores settings like this for each app. The settings values persist from one use of the app to the next. Furthermore, users can change settings directly using the built-in tool, as shown later in this chapter.

Using Preferences

Although there is no hard-and-fast rule, many people consider preferences to be settable from outside the app, possibly even at the time the app is installed. In addition, some preferences such as the user’s location or language preference are set using the operating system itself.

Preferences and Settings: A Case Study

This section uses a simple example of a setting for the name of an item in an app (“Chair” or “Student”). It shows how this can be implemented with Settings or the user defaults system rather than with a database or document.

The code for this example is downloadable as described in Chapter 1. (It is PreferencesApp.) The major steps in the process of implementing PreferencesApp are
  • Start from a built-in Xcode project template (Single View App in this case).

  • Add a Settings bundle to manage the settings (“Chair” or “Student” in this example).

  • Build an interface to your app for the settings.

  • Add an interface to show the app’s settings and version. (This is useful for debugging any app. I use it automatically when I build any app.)

Creating the PreferencesApp

Because this example focuses just on settings and preferences, the Single View App project template is a good place to start (Figure 9-1).
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig1_HTML.jpg
Figure 9-1.

Starting from the Single View App project template

You can use the basic settings such as naming your app. In the options shown in Figure 9-2, take a moment to look at the checkboxes at the bottom of the view. If you want to develop your own more complex preferences and other values, Core Data is a good tool to look into. It is implemented as a single user SQLite database that is built into Cocoa. If you are familiar with relational databases, it can be a good tool to use in implementing your own complex settings and preferences. When it comes to managing data in your app, you can use Settings and Core Data, as well as documents. In some cases, there are advantages to using separate data management strategies so that the app and its data are independent of one another.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig2_HTML.jpg
Figure 9-2.

Setting the options for PreferencesApp

You can use the general settings shown in Figure 9-3 for PreferencesApp. It’s also worth noting that PreferencesApp as implemented here doesn’t require any special support in your app until you get to the integration in the “Accessing the Settings Bundle From Your Code” section later in this chapter.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig3_HTML.jpg
Figure 9-3.

You don’t need special options to use Settings

Adding a Settings Bundle

What you do need to do to implement Settings in an iOS app is add a new file that contains a settings bundle. You can do this in your app using New ➤ File, as shown in Figure 9-4.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig4_HTML.jpg
Figure 9-4.

Adding a settings bundle to your app

Tip

When adding a settings bundle to your app, be careful to select the correct file. There are other settings bundles such as WatchKit Settings Bundle and, in the future, there are likely to be other settings bundles.

Make certain that you add the new file to the correct target in your app, as shown in Figure 9-5. (The group you place it in is important for organizing your files, but the target is absolutely essential.)
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig5_HTML.jpg
Figure 9-5.

Placing the new settings bundle in the right target

When you have added the settings bundle, you’ll see it in your project navigator, as shown in Figure 9-6.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig6_HTML.jpg
Figure 9-6.

Confirming that the settings bundle has been added to the project navigator

Note that inside the bundle is a group (en.lproj) containing some localized strings for the root of the bundle as well as a property list of root strings. You can use these as-is. The default values are shown in Figure 9-7.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig7_HTML.jpg
Figure 9-7.

You can use the default settings strings as-is

With the settings bundle added to your app, you can try it out using the built-in settings. Run the app in the simulator and look for Settings, as shown in Figure 9-8.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig8_HTML.jpg
Figure 9-8.

Using Settings in iOS

Scroll down to find PreferencesApp, as shown in Figure 9-9.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig9_HTML.jpg
Figure 9-9.

Tapping PreferencesApp in Settings

Open Root.plist in the settings bundle. You will see the default settings shown in Figure 9-10.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig10_HTML.jpg
Figure 9-10.

Initial settings

Open the Text Field item so you can see its values. Change the value of Default Value to Student, as shown in Figure 9-11.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig11_HTML.jpg
Figure 9-11.

Changing the Default Value to Student

You can take advantage of the autocapitalization style, as you can see in Figure 9-12. This means that the words of the entered text will be capitalized. Experiment with the other Settings commands and you’ll see that you have a lot of features built in that you don’t have to code yourself.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig12_HTML.jpg
Figure 9-12.

Adjusting the settings for your app

Finally, test Settings in the simulator, as shown in Figure 9-13. (You’ll notice that some items in Settings for an app are automatically added by iOS. The Siri & Search settings are an example of this.)

Accessing the Settings Bundle from Your Code

When a user adjusts Settings, that’s only the beginning. You need to be able to access the Settings values in your app. This section shows how to do so based on Settings, as shown in Figure 9-13.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig13_HTML.jpg
Figure 9-13.

Test settings

Start by reminding yourself that the Settings in iOS accesses the defaults database that is built into Cocoa. That database is managed by the UserDefaults class object (not an instance; the class). UserDefaults (the class object) has a function that returns the shared defaults object with the standard property. As noted previously, each item in UserDefaults has a key, and you can access it with code such as the following:
return UserDefaults.standard.bool (forKey: "name_preference")
This key is the identifier key in the property list. As you can see in Figure 9-14, if you start to type the code to access a key, it is completed for you.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig14_HTML.jpg
Figure 9-14.

Using the identifier key to access a user default property

You can test this by adding code to appDelegate application(:didFinishLaunchingWithptions:), as you can see in Figure 9-15.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig15_HTML.jpg
Figure 9-15.

Accessing a property in the user default Settings app

Adding a Settings Interface

The code shown in Figure 9-15 is executed only when the app launches. You can build your own interface to show a user defaults property whenever you want it. In a view controller of the main storyboard, add a button, as shown in Figure 9-16. (If you are using the Single View App project template, as shown in this chapter, the view controller to use is called ViewController.)
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig16_HTML.jpg
Figure 9-16.

Adding a button to the view controller

Remember to connect the button to an action in your app, as shown in Figure 9-17.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig17_HTML.jpg
Figure 9-17.

Connecting the button to an action

Add a breakpoint to the action so that you can check the value of the user default property, as shown in Figure 9-18.
../images/465467_1_En_9_Chapter/465467_1_En_9_Fig18_HTML.jpg
Figure 9-18.

Using a breakpoint to check the value

Summary

This chapter showed how to use the built-in user defaults preferences and/or Settings app to store values for your app. These values must be able to be stored in a property list and they should now be large data objects, but you can use them for many purposes other than building a large-scale data manager.

..................Content has been hidden....................

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