data storage - washington state universityholder/courses/mad/slides/11-storage.pdf ·...

37
Data Storage Mobile Applica,on Development in iOS School of EECS Washington State University Instructor: Larry Holder Mobile Applica,on Development in iOS 1 Xcode 11.4 with iOS 13.4 and Swift 5.2 is here!

Upload: others

Post on 20-Jun-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Data StorageMobile Applica,on Development in iOS

School of EECS

Washington State University

Instructor: Larry Holder

Mobile Applica,on Development in iOS 1

Xcode 11.4 withiOS 13.4 andSwift 5.2 is here!

Page 2: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Data Storage

• Already seen: UserDefaults

• File I/O: Read, Write, Codable

• Database support: CoreData

• Data in the cloud: Firebase

Mobile Application Development in iOS 2

Page 3: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O

• FileManager

– .default: singleton shared file manager for app

– Numerous methods for manipulaAng files

• FileManagerDelegate

– Constraint checking and error handling

Mobile Application Development in iOS 3

Page 4: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O Process• Get URL to directory

• Append file name to URL

• Convert data to String

• Use String.write(to: URL, atomically: Bool, encoding: .uA8) to write

– Atomically: write to auxiliary file first

• Use String(contentsOf: URL , encoding: .uA8) to read

• Both throw errors

Mobile Application Development in iOS 4

Page 5: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Write

Mobile Applica,on Development in iOS 5

func writeData(_ str: String, to fileName: String) -> Bool {if let directoryURL = FileManager.default.urls(for: .documentDirectory,

in: .userDomainMask).first {let fileURL = directoryURL.appendingPathComponent(fileName)do {

try str.write(to: fileURL, atomically: true, encoding: .utf8)return true

} catch {print("\(error)")

}} else {

print("Error accessing document directory.")}return false

}

Page 6: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Read

Mobile Applica,on Development in iOS 6

func readData(from fileName: String) -> String? {if let directoryURL = FileManager.default.urls(for: .documentDirectory,

in: .userDomainMask).first {let fileURL = directoryURL.appendingPathComponent(fileName)do {

let str = try String(contentsOf: fileURL, encoding: .utf8)return str

} catch {print("\(error)")

}} else {

print("Error accessing document directory.")}return nil

}

Page 7: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Codable

• Problem: Convert everything to a String ☹

• Solu5on: Codable types

– Can be encoded/decoded to common formats, e.g., JSON

– JSON data easily converted to/from String

• All basic types and containers are Codable

• Classes consis5ng of Codable proper5es are Codable

Mobile Application Development in iOS 7

Page 8: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Codable

Mobile Applica,on Development in iOS 8

class Player: Codable {var name: Stringvar health: Intvar inventory: [String]

init(name: String, health: Int) {self.name = nameself.health = healthself.inventory = []

}

func printPlayer() {print("Player: name = \(name), health = \(health),

inventory = \(inventory)")}

}

Page 9: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Codable

Mobile Applica,on Development in iOS 9

func writePlayers(_ players: [Player], to fileName: String) -> Bool{

let jsonEncoder = JSONEncoder()do {

let jsonData = try jsonEncoder.encode(players)if let jsonStr = String(data: jsonData, encoding: .utf8) {

if writeData(jsonStr, to: fileName) {return true

}}

} catch {print("\(error)")

}return false

}

Page 10: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

File I/O: Codable

Mobile Applica,on Development in iOS 10

func readPlayers(from fileName: String) -> [Player] {if let str = readData(from: fileName) {

if let jsonData = str.data(using: .utf8) {let jsonDecoder = JSONDecoder()do {

let players = try jsonDecoder.decode([Player].self,from: jsonData)

return players} catch {

print("\(error)")}

}}return []

}

Page 11: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Database Support• Core Data

– iOS-specific object store

• SQLite (www.sqlite.org)

– Cross-pla3orm table store (already available in iOS)

• Third-party opBons ($)

– Realm (realm.io) • Cross-pla)orm object store

– Firebase (firebase.google.com)

• Real2me Database: Cross-pla)orm JSON document store

• Cloud Firestore: Cross-pla)orm document store

Mobile Application Development in iOS 11

Page 12: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data• Check “Use Core Data” for

New Project

– Includes empty data model

– Includes boilerplate code

to create database

• Or, add Core Data model to

exis5ng project

Mobile Application Development in iOS 12

Page 13: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data Stack: Model

• Create Managed Object Model (Schema)

• Schema consists of enAAes, their aJributes, and

relaAonships

Mobile Application Development in iOS 13

Page 14: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data Stack:Persistent Container and Context

• Persistent container (NSPersistentContainer)

– Data store (the "database")

– Defined in AppDelegate.swiF

– Obtained from UIApplicaHon.shared.delegate

• Managed object context (NSManagedObjectContext)

– Tracks changes to data store unHl saved

– Obtained from NSPersistentContainer.viewContext

Mobile Application Development in iOS 14

Page 15: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data Stack: Access

Mobile Applica,on Development in iOS 15

import CoreData

class TableViewController: UITableViewController {

var managedObjectContext: NSManagedObjectContext!var appDelegate: AppDelegate!

override func viewDidLoad() {super.viewDidLoad()appDelegate = UIApplication.shared.delegate as? AppDelegatemanagedObjectContext = appDelegate.persistentContainer.viewContext

}}

Page 16: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Insert

• Methods

– NSEnHtyDescripHon.insertNewObject(forEnHtyName:

String, into: NSManagedObjectContext) ->

NSManagedObject

– NSManagedObject.setValue(value: Any?, forKey: String)

– NSManagedObjectContext.save()

Mobile Application Development in iOS 16

Page 17: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Insert

Mobile Applica,on Development in iOS 17

func addPlayer(name: String, health: Int) {let player = NSEntityDescription.insertNewObject(forEntityName:

"Player", into: self.managedObjectContext)player.setValue(name, forKey: "name")player.setValue(health, forKey: "health")appDelegate.saveContext() // In AppDelegate.swift

}

Page 18: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Fetch

• Methods

– NSFetchRequest<NSManagedObject>(en7tyName:

String) -> NSFetchRequest<NSManagedObject>

– NSFetchRequest<NSManagedObject>.predicate =

NSPredicate(format: String, args...)

– NSManagedObjectContext.fetch(request:

NSFetchRequest<NSManagedObject>) throws

Mobile Application Development in iOS 18

Page 19: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Fetch

Mobile Applica,on Development in iOS 19

func getPlayers() -> [NSManagedObject] {let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Player")var players: [NSManagedObject] = []do {

players = try self.managedObjectContext.fetch(fetchRequest)} catch {

print("getPlayers error: \(error)")}return players

}

func printPlayer(_ player: NSManagedObject) {let name = player.value(forKey: "name") as? Stringlet health = player.value(forKey: "health") as? Intprint("Player: name = \(name!), health = \(health!)")

}

Page 20: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Delete

• Methods

– NSManagedObjectContext.delete(object:

NSManagedObject)

– NSManagedObjectContext.save()

Mobile Application Development in iOS 20

Page 21: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Core Data: Delete

Mobile Applica,on Development in iOS 21

func removePlayersByName(_ name: String) {let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Player")fetchRequest.predicate = NSPredicate(format: "name == %@", name)var players: [NSManagedObject]!do {

players = try self.managedObjectContext.fetch(fetchRequest)} catch {

print("removePlayersByName error: \(error)")}for player in players {

managedObjectContext.delete(player)}appDelegate.saveContext() // In AppDelegate.swift

}

func removePlayer(_ player: NSManagedObject) {managedObjectContext.delete(player)appDelegate.saveContext()

}

Page 22: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

• firebase.google.com

• Authentication

• Realtime Database

– Cross-platform JSON document store (NoSQL)

• Cloud Firestore

– Cross-platform document store (NoSQL)

– Stores Collections of Documents

– Documents contain key/value pairs

Mobile Applica,on Development in iOS 22

Firebase

Page 23: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

• Create Google account

• Goto firebase.google.com

• "GO TO CONSOLE" and sign in

• Add project

Mobile Applica,on Development in iOS 23

Firebase Setup

Page 24: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firebase Setup• Add Firebase to app

– Register app

– Download config property list file and add to app

– Add Firebase SDK to app

• Cocoapods: pod 'Firebase/AnalyHcs'

– Add iniAalizaAon code

Mobile Application Development in iOS 24

Page 25: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firebase Setup

Mobile Applica,on Development in iOS 25

// AppDelegate.swift

import UIKitimport Firebase

@UIApplicationMainclass AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptionslaunchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// Override point for customization after application launch.FirebaseApp.configure()return true

}

// ...}

Page 26: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firebase Authentication• Pod 'Firebase/Auth'

• Enable authenHcaHon methods

Mobile Application Development in iOS 26

Page 27: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firebase Authen@ca@on

Mobile Applica,on Development in iOS 27

import FirebaseAuth

// Create userAuth.auth().createUser(withEmail: email, password: password)

{ authResult, error in// ...

}

// Sign in (existing user)Auth.auth().signIn(withEmail: email, password: password)

{ authResult, error in// ...

}

// Current userlet user = Auth.auth().currentUser

// Sign out current usertry? Auth.auth().signOut()

Firebase Authentication

Page 28: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Cloud Firestore: Create Database

Mobile Application Development in iOS 28

Page 29: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore Setup• Pod 'Firebase/Firestore'

• Pod 'FirebaseFirestoreSwiF'

• pod install (takes a while)

Mobile Application Development in iOS 29

import Firebase

var players: [Player] = []

let collection = Firestore.firestore().collection("players")

Page 30: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Player Class

Mobile Application Development in iOS 30

class Player {var name: Stringvar health: Intvar id: String?

init(name: String, health: Int) {self.name = nameself.health = health

}

init(dict: [String: Any]) {self.name = dict["name"] as! Stringself.health = dict["health"] as! Int

}

func toDict() -> [String: Any] {return ["name": name, "health": health]

}}

Page 31: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore: Insert• Collection.addDocument(data: [String: Any],

completion: ((Error?) -> Void)? ) -> DocumentReference

Mobile Application Development in iOS 31

func addPlayer(_ player: Player) {var ref: DocumentReference?ref = collection.addDocument(data: player.toDict()) { error in

if let err = error {print("Error adding document: \(err)")

} else {print("Document added with ID: \(ref!.documentID)")player.id = ref!.documentID

}}

}

Page 32: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore Database

Mobile Application Development in iOS 32

Page 33: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore: Fetch• Collection.getDocuments(completion:

((QuerySnapshot?, Error?) -> Void)?)

Mobile Application Development in iOS 33

func loadPlayers() {collection.getDocuments() { (querySnapshot, error) in

if let err = error {print("Error getting documents: \(err)")

} else {self.players = []for document in querySnapshot!.documents {

print("\(document.documentID) => \(document.data())")let player = Player(dict: document.data())player.id = document.documentIDself.players.append(player)

}self.tableView.reloadData()

}}

}

Page 34: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore: Delete• Collection. Document(documentID).delete(completion:

((Error?) -> Void)?)

Mobile Applica,on Development in iOS 34

func removePlayer(_ player: Player) {collection.document(player.id!).delete() { error in

if let err = error {print("Error removing document: \(err)")

} else {print("Document successfully removed")

}}

}

Page 35: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore: Listener• Listeners react to changes to the data store

• Various listeners available

– Documents

– Collections

• E.g., receive snapshot of collection when anything changes:

– Collection.addSnapshotListener(completion:((QuerySnapshot?, Error?) -> Void)?)

Mobile Applica,on Development in iOS 35

Page 36: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Firestore: Listener

Mobile Applica,on Development in iOS 36

func addListener() {collection.addSnapshotListener { querySnapshot, error in

if let err = error {print("Error retrieving collection: \(err)")

} else {self.players = []for document in querySnapshot!.documents {

let documentID = document.documentIDlet data = document.data()print("listener: \(documentID) => \(data)")let player = Player(dict: data)player.id = documentIDself.players.append(player)

}self.tableView.reloadData()

}}

}

Page 37: Data Storage - Washington State Universityholder/courses/MAD/slides/11-Storage.pdf · –Cross-pla3orm table store (already available in iOS) •Third-party opons ($) –Realm (realm.io)

Resources

• File I/O: developer.apple.com/documentation/foundation/filemanager

• Codable types: developer.apple.com/documentation/swift/codable

• Core Data

– developer.apple.com/documentation/coredata

– www.raywenderlich.com/7569-getting-started-with-core-data-tutorial

• Firebase: firebase.google.com

• Firestore: firebase.google.com/docs/firestore

Mobile Applica,on Development in iOS 37