Data Persistence iOS Application Development Professor William Hoff Data Persistence

• Apps often need to persist data • When users make changes, they expect to find those changes when they launch the app again • We can do this by writing data to the file system

2 Sandbox

• Your app sees the iOS file system like a normal UNIX file system • Every app gets its own /Documents which is referred to as its sandbox • Your app can only read and write from that directory • This helps with - Security - Privacy - Cleanup

3 iOS

For security purposes, an app’s interactions with the file system are limited to the directories inside the An iOS app may app’s sandbox create directory. additional directories in the Documents, Library, and tmp directories.

During installation of a new app, the installer creates a number of container directories for the app inside the sandbox directory. https://developer.apple.com/library/content/documentation/FileManagement/ Conceptual/FileSystemProgrammingGuide/FileSystemOverview/ 4 FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW13 Viewing the Sandbox

• In the Finder go into your home directory • Hold down the option key and click on “Go” - This makes the “Library” directory visible • Go to Library/Developer/CoreSimulator/Devices/Device GUID/ - These are all the simulated devices - The GUIDs are globally unique identifiers, generated automatically by Xcode • Go inside one of these - The file “device.plist” shows what the simulated device is • Drill down into data/Containers/Data/Application - The GUIDs represent the installed applications - Inside these are the subdirectories: Documents, Library, and tmp • The same file structure exists on devices

5 Directories

Directory Description This is the app’s bundle. This directory contains the app and all of its resources. You cannot write to this directory. The bundle AppName.app directory is signed at installation time. You can gain read-only access to any resources stored in the apps bundle. Use this directory to store -generated content. The contents of this directory can be made available to the user through file Documents/ sharing; therefore, his directory should only contain files that you may wish to expose to the user.

This is the top-level directory for any files that are not user data Backed up files. You typically put files in one of several standard by iTunes subdirectories. iOS apps commonly use the Application Support and iCloud Library/ and Caches subdirectories; however, you can create custom subdirectories. Use the Library subdirectories for any files you don’t want exposed to the user. Your app should not use these directories for user data files. Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove tmp/ files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running.

6 Possible ways to persist data

• Property lists - Easiest method; but can’t save custom objects - Best for static data; or preferences • Object archives (or archiving) - You can archive a custom object if it conforms to the NSCoding protocol. • SQLite3 (iOS’s embedded relational database) - Can selectively retrieve objects that meet certain criteria • Core Data (Apple’s provided persistence tool)

7 Property Lists

• Limited to certain serializable objects: - Array or NSArray - NSMutableArray - Dictionary or NSDictionary - NSData - NSMutableData - String or NSString - NSMutableString - NSNumber - NSDate

8 to plist file in bundle

• If your plist file is part of your bundle, you can get its full path name using

let filepath = Bundle.main.path(forResource: "myfilename", ofType: "plist")

- The type of filepath is optional String

9 Path to plist file in Documents

• NSSearchPathForDirectoriesInDomain() will locate a directory • To retrieve the path to the Documents directory:

let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true)

- This returns an array of Strings with the documents directory in the first position • To create a string with the full path name to your file:

let dir = path[0] as NSString let filePath = dir.appendingPathComponent(filename)

10 File System

• The FileManager class enables you to perform many generic file-system operations - Example: manipulate files (move, copy, delete, etc) - To check to see if a file exists at a given path: if FileManager.default.fileExists(atPath: filePath!) { :

11 Reading plists

• Once we have a path to a file, we can read or write it • We should read the data each time the app loads (ie, in viewDidLoad()) • Example: - In our “Countries” app, we had a dictionary of the form [String : [String]] - To read the plist into a Swift dictionary: myDictionary = NSDictionary(contentsOfFile: path!) as! [String : [String]]

12 Writing out our data

• When the app goes inactive, we should write out our data • You could do this in the applicationWillResignActive() method in the AppDelegate class • You can also do it in your ViewController class, if you “register” this class to get the notification that the app will go inactive

13 Communication

In iOS there are four common patterns for objects to communicate: 1. Target-Action: a single object calls a single method when a single event occurs 2. Delegation: an object responds to numerous methods to modify or add behavior 3. Notification: Register an object to be notified when an event occurs 4. Key-Value Observing (KVO): register to be one of many objects notified when single property of another object changes.

14 Notifications

• A notification is a callback mechanism that can inform multiple objects when an event occurs • A NotificationCenter manages the notification process • Objects register for the notifications they’re interested in • Notification senders post notifications to a notification center. • The notification center notifies any objects registered for that notification.

15