Data Storage
Mobile Applica,on Development in iOS School of EECS Washington State University Instructor: Larry Holder
Mobile Applica,on Development in iOS 1
Data Storage Mobile Applica,on Development in iOS School of EECS - - PowerPoint PPT Presentation
Xcode 11.4 with iOS 13.4 and Swift 5.2 is here! Data Storage Mobile Applica,on Development in iOS School of EECS Washington State University Instructor: Larry Holder Mobile Applica,on Development in iOS 1 Data Storage Already seen:
Mobile Applica,on Development in iOS School of EECS Washington State University Instructor: Larry Holder
Mobile Applica,on Development in iOS 1
Mobile Application Development in iOS 2
Mobile Application Development in iOS 3
to write
– Atomically: write to auxiliary file first
Mobile Application Development in iOS 4
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 }
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 }
– Can be encoded/decoded to common formats, e.g., JSON – JSON data easily converted to/from String
Mobile Application Development in iOS 7
Mobile Applica,on Development in iOS 8
class Player: Codable { var name: String var health: Int var inventory: [String] init(name: String, health: Int) { self.name = name self.health = health self.inventory = [] } func printPlayer() { print("Player: name = \(name), health = \(health), inventory = \(inventory)") } }
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 }
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 [] }
– iOS-specific object store
– Cross-pla3orm table store (already available in iOS)
– Realm (realm.io)
– Firebase (firebase.google.com)
Mobile Application Development in iOS 11
– Includes empty data model – Includes boilerplate code to create database
Mobile Application Development in iOS 12
Mobile Application Development in iOS 13
– Data store (the "database") – Defined in AppDelegate.swiF – Obtained from UIApplicaHon.shared.delegate
– Tracks changes to data store unHl saved – Obtained from NSPersistentContainer.viewContext
Mobile Application Development in iOS 14
Mobile Applica,on Development in iOS 15
import CoreData class TableViewController: UITableViewController { var managedObjectContext: NSManagedObjectContext! var appDelegate: AppDelegate!
super.viewDidLoad() appDelegate = UIApplication.shared.delegate as? AppDelegate managedObjectContext = appDelegate.persistentContainer.viewContext } }
– NSEnHtyDescripHon.insertNewObject(forEnHtyName: String, into: NSManagedObjectContext) -> NSManagedObject – NSManagedObject.setValue(value: Any?, forKey: String) – NSManagedObjectContext.save()
Mobile Application Development in iOS 16
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 }
– 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
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? String let health = player.value(forKey: "health") as? Int print("Player: name = \(name!), health = \(health!)") }
Mobile Application Development in iOS 20
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() }
– Cross-platform JSON document store (NoSQL)
– Cross-platform document store (NoSQL) – Stores Collections of Documents – Documents contain key/value pairs
Mobile Applica,on Development in iOS 22
Mobile Applica,on Development in iOS 23
Mobile Application Development in iOS 24
Mobile Applica,on Development in iOS 25
// AppDelegate.swift import UIKit import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. FirebaseApp.configure() return true } // ... }
Mobile Application Development in iOS 26
Mobile Applica,on Development in iOS 27
import FirebaseAuth // Create user Auth.auth().createUser(withEmail: email, password: password) { authResult, error in // ... } // Sign in (existing user) Auth.auth().signIn(withEmail: email, password: password) { authResult, error in // ... } // Current user let user = Auth.auth().currentUser // Sign out current user try? Auth.auth().signOut()
Mobile Application Development in iOS 28
Mobile Application Development in iOS 29
import Firebase var players: [Player] = [] let collection = Firestore.firestore().collection("players")
Mobile Application Development in iOS 30
class Player { var name: String var health: Int var id: String? init(name: String, health: Int) { self.name = name self.health = health } init(dict: [String: Any]) { self.name = dict["name"] as! String self.health = dict["health"] as! Int } func toDict() -> [String: Any] { return ["name": name, "health": health] } }
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 } } }
Mobile Application Development in iOS 32
((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.documentID self.players.append(player) } self.tableView.reloadData() } } }
((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") } } }
– Documents – Collections
– Collection.addSnapshotListener(completion: ((QuerySnapshot?, Error?) -> Void)?)
Mobile Applica,on Development in iOS 35
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.documentID let data = document.data() print("listener: \(documentID) => \(data)") let player = Player(dict: data) player.id = documentID self.players.append(player) } self.tableView.reloadData() } } }
– developer.apple.com/documentation/coredata – www.raywenderlich.com/7569-getting-started-with-core-data-tutorial
Mobile Applica,on Development in iOS 37