KEMBAR78
Persistence on iOS | PDF
PERSISTENCE ON IOS
AGENDA
NSUserDefaults
Keychain
Filesystem
Encoding/Decoding
Advanced Persistence Technologies
NSUSERDEFAULTS
NSUSERDEFAULTS
NSUserDefaults allows to store Strings, Numbers, Dates, NSData and
Arrays or Dictionaries thereof
Usually should be used to store user preferences, can be used to
store small amount of persistent information
Should never be used for sensitive data


NSUserDefaults.standardUserDefaults().setBool(false, forKey:
"UserAccountCreated")
KEYCHAIN
KEYCHAIN
Is used to store sensitive information, such as passwords
All information is stored encrypted
Apple’s API is arcane - Open Source Libraries such as
SSKeychain will make your life easier!
FILESYSTEM
FILESYSTEM
Apps can only read/write files
within their sandbox
Diagram shows different
sandbox subdirectories
AppName
Documents
Library
Caches
Preferences
tmp
AppName.app
IMPORTANT DIRECTORIES
<Application_Home>/AppName.app
This is the main bundle of the App. All of the content of this
folder is created at compile time (based on files added in
Xcode) and cannot be modified at runtime!
Bundle contains binary along with resource files
IMPORTANT DIRECTORIES
<Application_Home>/Documents/
This is the place to store data that is critical to your application
(user generated content, content that cannot be automatically
regenerated)
This directory is backed up with iTunes Backups and it can be
made available to iTunes users via Filesharing
IMPORTANT DIRECTORIES
<Application_Home>/Library/tmp
Use this to store files that you do need to to persist
permanently. You are responsible for removing files from this
directory when they are no longer needed
All files in the Library directory (excluding the Library/Caches
directory) are backed up to iTunes by default. You can change
this by using a file attribute
IMPORTANT DIRECTORIES
<Application_Home>/Library/Caches
This folder should be used to store cached information (e.g.
profile pictures that have been downloaded)
iOS will remove file from this directory when it needs to free
disk space, your app needs to be able to handle deletion of
file in the caches directory
The content of this folder is not backed up to iTunes
ACCESSING FILES
Accessing files within the application bundle:

let path = NSBundle.mainBundle().pathForResource("file1", ofType: ".jpg")
if let path = path {
let image = UIImage(contentsOfFile:path)
}
Short form:
UIImage(named: "file1.jpg")
ACCESSING FILES
Accessing files within the documents directory:

let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory,
inDomains: .UserDomainMask)
if let documentDirectory: NSURL = urls.first {
let documentURL =
documentDirectory.URLByAppendingPathComponent("txtFile.txt")
do {
let content = try String(contentsOfURL: documentURL)
} catch let error as NSError {
print(error.localizedDescription)
WRITING FILES
Writing a file to the documents directory:

let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory,
inDomains: .UserDomainMask)
if let documentDirectory: NSURL = urls.first {
let documentURL =
documentDirectory.URLByAppendingPathComponent("txtFile.txt")
// data you want to write to file
let data = NSData()
data.writeToURL(documentURL, atomically: true)
}
WHEN TO USE THE
FILESYSTEM?
Primarily when storing/caching binary data such as images
Can also be used to store serialized Objects, allows to persist
Objects and Object Graphs from your application
ENCODING/DECODING
ENCODING/DECODING
Encoding: Creating a binary/textual representation (that can
be stored on disk, transferred via network) from an object
graph
Decoding: Creating an object graph from a binary/textual
representation
SERIALIZATION IS A SUBSET
OF ENCODING
User User
Product Product
Product
Product
Object Graph Serialized Document
{
UserID: 934235,
Username: "Ben-G",
Purchases:
[
{
ProductID: 1278123,
Price: 99,
Name: "Apple TV"
}
],
[
{
ProductID: 7238483,
Price: 299,
Name: "Kitchen Set"
}
],
}
Serialization
STEP 1: IMPLEMENT NSCODING
class Movie: NSObject, NSCoding {
var title: String
var duration: Int
init(title: String, duration: Int) {
self.title = title
self.duration = duration
}
required convenience init?(coder aDecoder: NSCoder) {
guard let title = aDecoder.decodeObjectForKey("title") as? String,
let duration = aDecoder.decodeObjectForKey("duration") as? Int
else { return nil }
self.init(title: title, duration: duration)
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.title, forKey: "title")
coder.encodeObject(self.duration, forKey: "duration")
}
}
STEP 2: USER ARCHIVER
NSKeyedArchiver.archiveRootObject(movies, toFile: "/path/to/archive")
Archive
let unarchivedMovies = NSKeyedUnarchiver.unarchiveObjectWithFile(

"/path/to/archive") as? [Movie]
Unarchive
WHEN TO USE NSCODING
Use NSCoding when main goal of persistence in your App is
to store the current state of the application
If you additionally want to create queries, need migrations,
etc, there are better solutions (e.g., CoreData)
ADVANCED PERSISTENCE
TECHNOLOGIES
WHAT’S MISSING?
Querying / selecting a subset of object graph
Saving individual objects independent of entire graph
Simple versioning of data model
SQLITE
Industry standard for lightweight SQL DBMS access in
applications; extremely fast
Available for all major platforms
Commonly not used for persistence in iOS applications
A lot of boilerplate code
No built-in Swift Object <-> SQLite mapping
CORE DATA
“Core Data provides an infrastructure for change management and
for saving objects to and retrieving them from storage. It can use
SQLite as one of its persistent store types. It is not, though, in and of
itself a database. (To emphasize this point: you could for example
use just an in-memory store in your application. You could use Core
Data for change tracking and management, but never actually save
any data in a file.)”
Source: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdTechnologyOverview.html , 09/04/2014
CORE DATA
… is sophisticated enough to deserve its own lecture!
SUMMARY
SUMMARY
NSUserDefaults is the easiest way to persist a small amount of
information in an application
Security relevant information should be stored in the Keychain
Apps run in a sandbox where they have access to their bundle and
different types of directories
The entire object graph of an application can be persisted using
NSCoding and NSArchiver; good solution if you merely need to store
the state of your app and don’t need queries or migrations
ADDITIONAL RESOURCES
• Apple’s Keychain Programming Guide
• NSCoding on NSHipster

Persistence on iOS

  • 2.
  • 3.
  • 4.
  • 5.
    NSUSERDEFAULTS NSUserDefaults allows tostore Strings, Numbers, Dates, NSData and Arrays or Dictionaries thereof Usually should be used to store user preferences, can be used to store small amount of persistent information Should never be used for sensitive data 
 NSUserDefaults.standardUserDefaults().setBool(false, forKey: "UserAccountCreated")
  • 6.
  • 7.
    KEYCHAIN Is used tostore sensitive information, such as passwords All information is stored encrypted Apple’s API is arcane - Open Source Libraries such as SSKeychain will make your life easier!
  • 8.
  • 9.
    FILESYSTEM Apps can onlyread/write files within their sandbox Diagram shows different sandbox subdirectories AppName Documents Library Caches Preferences tmp AppName.app
  • 10.
    IMPORTANT DIRECTORIES <Application_Home>/AppName.app This isthe main bundle of the App. All of the content of this folder is created at compile time (based on files added in Xcode) and cannot be modified at runtime! Bundle contains binary along with resource files
  • 11.
    IMPORTANT DIRECTORIES <Application_Home>/Documents/ This isthe place to store data that is critical to your application (user generated content, content that cannot be automatically regenerated) This directory is backed up with iTunes Backups and it can be made available to iTunes users via Filesharing
  • 12.
    IMPORTANT DIRECTORIES <Application_Home>/Library/tmp Use thisto store files that you do need to to persist permanently. You are responsible for removing files from this directory when they are no longer needed All files in the Library directory (excluding the Library/Caches directory) are backed up to iTunes by default. You can change this by using a file attribute
  • 13.
    IMPORTANT DIRECTORIES <Application_Home>/Library/Caches This foldershould be used to store cached information (e.g. profile pictures that have been downloaded) iOS will remove file from this directory when it needs to free disk space, your app needs to be able to handle deletion of file in the caches directory The content of this folder is not backed up to iTunes
  • 14.
    ACCESSING FILES Accessing fileswithin the application bundle:
 let path = NSBundle.mainBundle().pathForResource("file1", ofType: ".jpg") if let path = path { let image = UIImage(contentsOfFile:path) } Short form: UIImage(named: "file1.jpg")
  • 15.
    ACCESSING FILES Accessing fileswithin the documents directory:
 let fileManager = NSFileManager.defaultManager() let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) if let documentDirectory: NSURL = urls.first { let documentURL = documentDirectory.URLByAppendingPathComponent("txtFile.txt") do { let content = try String(contentsOfURL: documentURL) } catch let error as NSError { print(error.localizedDescription)
  • 16.
    WRITING FILES Writing afile to the documents directory:
 let fileManager = NSFileManager.defaultManager() let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) if let documentDirectory: NSURL = urls.first { let documentURL = documentDirectory.URLByAppendingPathComponent("txtFile.txt") // data you want to write to file let data = NSData() data.writeToURL(documentURL, atomically: true) }
  • 17.
    WHEN TO USETHE FILESYSTEM? Primarily when storing/caching binary data such as images Can also be used to store serialized Objects, allows to persist Objects and Object Graphs from your application
  • 18.
  • 19.
    ENCODING/DECODING Encoding: Creating abinary/textual representation (that can be stored on disk, transferred via network) from an object graph Decoding: Creating an object graph from a binary/textual representation
  • 20.
    SERIALIZATION IS ASUBSET OF ENCODING User User Product Product Product Product Object Graph Serialized Document { UserID: 934235, Username: "Ben-G", Purchases: [ { ProductID: 1278123, Price: 99, Name: "Apple TV" } ], [ { ProductID: 7238483, Price: 299, Name: "Kitchen Set" } ], } Serialization
  • 21.
    STEP 1: IMPLEMENTNSCODING class Movie: NSObject, NSCoding { var title: String var duration: Int init(title: String, duration: Int) { self.title = title self.duration = duration } required convenience init?(coder aDecoder: NSCoder) { guard let title = aDecoder.decodeObjectForKey("title") as? String, let duration = aDecoder.decodeObjectForKey("duration") as? Int else { return nil } self.init(title: title, duration: duration) } func encodeWithCoder(coder: NSCoder) { coder.encodeObject(self.title, forKey: "title") coder.encodeObject(self.duration, forKey: "duration") } }
  • 22.
    STEP 2: USERARCHIVER NSKeyedArchiver.archiveRootObject(movies, toFile: "/path/to/archive") Archive let unarchivedMovies = NSKeyedUnarchiver.unarchiveObjectWithFile(
 "/path/to/archive") as? [Movie] Unarchive
  • 23.
    WHEN TO USENSCODING Use NSCoding when main goal of persistence in your App is to store the current state of the application If you additionally want to create queries, need migrations, etc, there are better solutions (e.g., CoreData)
  • 24.
  • 25.
    WHAT’S MISSING? Querying /selecting a subset of object graph Saving individual objects independent of entire graph Simple versioning of data model
  • 26.
    SQLITE Industry standard forlightweight SQL DBMS access in applications; extremely fast Available for all major platforms Commonly not used for persistence in iOS applications A lot of boilerplate code No built-in Swift Object <-> SQLite mapping
  • 27.
    CORE DATA “Core Dataprovides an infrastructure for change management and for saving objects to and retrieving them from storage. It can use SQLite as one of its persistent store types. It is not, though, in and of itself a database. (To emphasize this point: you could for example use just an in-memory store in your application. You could use Core Data for change tracking and management, but never actually save any data in a file.)” Source: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdTechnologyOverview.html , 09/04/2014
  • 28.
    CORE DATA … issophisticated enough to deserve its own lecture!
  • 29.
  • 30.
    SUMMARY NSUserDefaults is theeasiest way to persist a small amount of information in an application Security relevant information should be stored in the Keychain Apps run in a sandbox where they have access to their bundle and different types of directories The entire object graph of an application can be persisted using NSCoding and NSArchiver; good solution if you merely need to store the state of your app and don’t need queries or migrations
  • 31.
    ADDITIONAL RESOURCES • Apple’sKeychain Programming Guide • NSCoding on NSHipster