Swift - Möglichkeiten Daten zu speichern: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
(Einführung)
 
(6 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 8: Zeile 8:
 
# '''Core Data:''' Core Data ist ein Framework für objektrelationales Mapping (ORM), mit dem Entwickler auf das Datenmodell der App zugreifen können. Es ist eine leistungsstarke und flexible Lösung zum Speichern und Abrufen großer Datenmengen und bietet Funktionen wie Rückgängig- und Wiederholen-Funktionen, Änderungsverfolgung und Datenvalidierung.
 
# '''Core Data:''' Core Data ist ein Framework für objektrelationales Mapping (ORM), mit dem Entwickler auf das Datenmodell der App zugreifen können. Es ist eine leistungsstarke und flexible Lösung zum Speichern und Abrufen großer Datenmengen und bietet Funktionen wie Rückgängig- und Wiederholen-Funktionen, Änderungsverfolgung und Datenvalidierung.
 
# '''Realm:''' Realm ist ein von Dritten bereitgestelltes ORM, das Core Data ähnlich ist, aber im Allgemeinen als leichter und schneller gilt.
 
# '''Realm:''' Realm ist ein von Dritten bereitgestelltes ORM, das Core Data ähnlich ist, aber im Allgemeinen als leichter und schneller gilt.
# '''File I/O:''' Dies ist die traditionelle Methode zum Speichern von Daten in iOS-Apps. Entwickler können Daten mithilfe des Foundation-Frameworks von und auf das lokale Dateisystem der App lesen und schreiben.
+
# '''Codable - File I/O:''' Dies ist die traditionelle Methode zum Speichern von Daten in iOS-Apps. Entwickler können Daten mithilfe des Foundation-Frameworks von und auf das lokale Dateisystem der App lesen und schreiben. Codable hilft dabei zum En- und Dekodieren von Objekten.
 
# '''Cloud Service:''' Durch die Verwendung von Cloud-Service-Anbietern wie AWS, Firebase oder Firestore kann die Daten auf deren Servern gespeichert werden, anstatt auf dem lokalen Gerät. Dieser Ansatz eignet sich, wenn die Daten unter verschiedenen Benutzern geteilt werden oder auf mehreren Geräten zugänglich sein sollen.
 
# '''Cloud Service:''' Durch die Verwendung von Cloud-Service-Anbietern wie AWS, Firebase oder Firestore kann die Daten auf deren Servern gespeichert werden, anstatt auf dem lokalen Gerät. Dieser Ansatz eignet sich, wenn die Daten unter verschiedenen Benutzern geteilt werden oder auf mehreren Geräten zugänglich sein sollen.
 +
 +
[[Datei:Swift-ios-DatenSpeichern.jpg|800px|zentriert]]
  
 
Letztlich hängt die Wahl der Methode zum Speichern von Daten von den spezifischen Anforderungen Ihrer App ab, einschließlich der Menge an zu speichernder Daten, der Komplexität des Datenmodells und den Anforderungen an die Datensynchronisierung und Sicherung.
 
Letztlich hängt die Wahl der Methode zum Speichern von Daten von den spezifischen Anforderungen Ihrer App ab, einschließlich der Menge an zu speichernder Daten, der Komplexität des Datenmodells und den Anforderungen an die Datensynchronisierung und Sicherung.
  
 
== User Defaults ==
 
== User Defaults ==
 +
[[Swift - UserDefaults]]
  
 
In iOS ist UserDefaults eine bequeme Klasse zum Speichern von kleinen Mengen an benutzerspezifischen Daten. Es wird von einer plist-Datei unterstützt, die ein einfaches Schlüssel-Wert-Speicherformat ist.
 
In iOS ist UserDefaults eine bequeme Klasse zum Speichern von kleinen Mengen an benutzerspezifischen Daten. Es wird von einer plist-Datei unterstützt, die ein einfaches Schlüssel-Wert-Speicherformat ist.
 
Um einen '''Wert für einen Schlüssel''' zu setzen, verwenden Sie die Methode set:
 
 
UserDefaults.standard.set("Hallo, Welt!", forKey: "Begrüßung")
 
 
Um den Wert für einen Schlüssel abzurufen, verwenden Sie die Methode object(forKey:):
 
 
let begrüßung = UserDefaults.standard.object(forKey: "Begrüßung") as? String
 
 
Sie können auch die Methode '''set''' verwenden, um andere Typen wie Bool, Int, Float, Double, URL und Data zu speichern:
 
 
UserDefaults.standard.set(true, forKey: "istErsterStart")
 
let istErsterStart = UserDefaults.standard.bool(forKey: "istErsterStart")
 
 
Sie können auch die Methode '''removeObject(forKey:)''' verwenden, um einen Wert für einen Schlüssel zu entfernen:
 
 
UserDefaults.standard.removeObject(forKey: "Begrüßung")
 
 
Es ist wichtig zu beachten, dass UserDefaults für kleine Mengen an Daten gedacht ist und nicht für große Dateien oder vertrauliche Daten geeignet ist.
 
  
 
== Beispiele ==
 
== Beispiele ==

Aktuelle Version vom 28. Januar 2023, 11:37 Uhr

Links[Bearbeiten]

Swift (Programmiersprache)

Einführung[Bearbeiten]

Es gibt mehrere Möglichkeiten, Benutzerdaten wie Notizen oder Einkaufslisten in einer iPhone-App, die in Swift geschrieben ist, zu speichern. Einige der populärsten Optionen sind:

  1. User Defaults: Dies ist eine einfache und einfach zu verwendende Methode zum Speichern von kleinen Mengen an Benutzerdaten. Es speichert Daten im Schlüssel-Wert-Paar-Format und die Daten werden automatisch gespeichert, wenn die App geschlossen wird oder im Hintergrund läuft.
  2. Core Data: Core Data ist ein Framework für objektrelationales Mapping (ORM), mit dem Entwickler auf das Datenmodell der App zugreifen können. Es ist eine leistungsstarke und flexible Lösung zum Speichern und Abrufen großer Datenmengen und bietet Funktionen wie Rückgängig- und Wiederholen-Funktionen, Änderungsverfolgung und Datenvalidierung.
  3. Realm: Realm ist ein von Dritten bereitgestelltes ORM, das Core Data ähnlich ist, aber im Allgemeinen als leichter und schneller gilt.
  4. Codable - File I/O: Dies ist die traditionelle Methode zum Speichern von Daten in iOS-Apps. Entwickler können Daten mithilfe des Foundation-Frameworks von und auf das lokale Dateisystem der App lesen und schreiben. Codable hilft dabei zum En- und Dekodieren von Objekten.
  5. Cloud Service: Durch die Verwendung von Cloud-Service-Anbietern wie AWS, Firebase oder Firestore kann die Daten auf deren Servern gespeichert werden, anstatt auf dem lokalen Gerät. Dieser Ansatz eignet sich, wenn die Daten unter verschiedenen Benutzern geteilt werden oder auf mehreren Geräten zugänglich sein sollen.
Fehler beim Erstellen des Vorschaubildes: Datei fehlt

Letztlich hängt die Wahl der Methode zum Speichern von Daten von den spezifischen Anforderungen Ihrer App ab, einschließlich der Menge an zu speichernder Daten, der Komplexität des Datenmodells und den Anforderungen an die Datensynchronisierung und Sicherung.

User Defaults[Bearbeiten]

Swift - UserDefaults

In iOS ist UserDefaults eine bequeme Klasse zum Speichern von kleinen Mengen an benutzerspezifischen Daten. Es wird von einer plist-Datei unterstützt, die ein einfaches Schlüssel-Wert-Speicherformat ist.

Beispiele[Bearbeiten]

Speichern von JSON Daten mit File I/O[Bearbeiten]

Siehe auch

Swift JSONEncoder 
Swift & JSON
struct Setlist: Codable {
    var title: String = "Default"
    var songs = [Song]()

    mutating func addSong(title: String, frequency: Float){
        print("Setlist::addSong")
        songs.append(Song(title:title, frequency: frequency))
    }
}

struct Song: Codable {
    let title: String
    let frequency: Float
}

// convert Setlist to json Data
let setlist = Setlist()
setlist.addSong(title: "song1", frequency: 44.1)
let encoder = JSONEncoder()
guard let encoded = try? encoder.encode(setlist) else {
    print("Encoding Failed")
    return
}

// write json Data to file
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent("setlist.json")
do {
    try encoded.write(to: fileURL, options: .atomic)
} catch {
    print("Error saving file: \(error)")
}

In diesem Beispiel wird die JSONEncoder Klasse verwendet, um eine Instanz des Structs Setlist in ein JSON-kodiertes Data-Objekt umzuwandeln. Das erzeugte JSON-kodierte Data wird in einer Datei gespeichert . In diesem Fall wird die Datei "setlist.json" im Dokumentenverzeichnis des Geräts gespeichert. Es ist zu beachten, dass es je nach Anwendungsfall sinnvoll sein kann, die Daten an einem anderen Ort oder in einem anderen Format zu speichern.

JSON Data Objekt als String ausgeben[Bearbeiten]

if let jsonString = String(data: encoded, encoding: .utf8) {
    print(jsonString)
} else {
    print("Could not convert encoded Data to String")
}

Dieser Code verwendet encoded Data und wandelt es in einen String um, indem es es decodiert und UTF-8 als Encoding verwendet. Wenn die Konvertierung erfolgreich ist, wird der Inhalt des Strings auf der Konsole ausgegeben. Es ist zu beachten, dass der JSON String nicht immer lesbar ausfällt, da die Reihenfolge der Werte innerhalb des Objekts oder des Arrays unvorhersehbar ist.

Speichern von Daten mit CoreData[Bearbeiten]

Das Speichern von Instanzen des Structs Setlist in Core Data erfordert einige zusätzliche Schritte im Vergleich zu User Defaults, da Core Data ein umfangreicheres Framework ist. Hier ist ein Beispiel dafür, wie dies mit Swift und Core Data erreicht werden kann:

import CoreData

struct Setlist {
    var title: String = "Default"
    var songs = [Song]()
    var objectID: NSManagedObjectID?
    
    mutating func addSong(title: String, frequency: Float){
        print("Setlist::addSong")
        songs.append(Song(title:title, frequency: frequency))
    }
}

struct Song {
    let title: String
    let frequency: Float
}

// To Save
func saveSetlist(_ setlist: Setlist) {
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
    let managedContext = appDelegate.persistentContainer.viewContext
    let setlistEntity = NSEntityDescription.entity(forEntityName: "SetlistEntity", in: managedContext)!
    let setlistMO = NSManagedObject(entity: setlistEntity, insertInto: managedContext)
    setlistMO.setValue(setlist.title, forKey: "title")
    
    var songMOs = [NSManagedObject]()
    for song in setlist.songs {
        let songEntity = NSEntityDescription.entity(forEntityName: "SongEntity", in: managedContext)!
        let songMO = NSManagedObject(entity: songEntity, insertInto: managedContext)
        songMO.setValue(song.title, forKey: "title")
        songMO.setValue(song.frequency, forKey: "frequency")
        songMOs.append(songMO)
    }
    setlistMO.setValue(NSOrderedSet(array: songMOs), forKey: "songs")
    setlist.objectID = setlistMO.objectID
    do {
        try managedContext.save()
    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }
}

// To Retrieve
func fetchSetlist(with objectID: NSManagedObjectID) -> Setlist? {
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return nil }
    let managedContext = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "SetlistEntity")
    fetchRequest.predicate = NSPredicate(format: "self == %@", objectID as CVarArg)
    do {
        let setlistMO = try managedContext.fetch(fetchRequest).first
        guard let title = setlistMO?.value(forKey: "title") as? String, let songsMO = setlistMO?.value(forKey: "songs") as? Set<NSManagedObject> else {
            return nil
        }
        var songs = [Song]()
        forsongMO in songsMO {
             let title = songMO.value(forKey: "title") as? String, let frequency = songMO.value(forKey: "frequency") as? Float else {
                 continue
             }
             songs.append(Song(title: title, frequency: frequency))
        }
        var setlist = Setlist(title: title, songs: songs)
        setlist.objectID = objectID
        return setlist
    } catch let error as NSError {
        print("Could not fetch. (error), (error.userInfo)")
    return nil
    }
}

Dieses Beispiel verwendet Core Data, um Instanzen des Structs Setlist zu speichern und abzurufen. Es verwendet NSManagedObjects, um die Entitäten von Setlist und Song im Datenmodell darzustellen und die Beziehungen zwischen ihnen zu verwalten. Bitte beachten Sie, dass es hier nur um ein Beispiel geht und dass Core Data viele weitere Funktionen bietet, die je nach Anwendungsfall sinnvoll sein können.

Speichern mit SQLite und FMDB[Bearbeiten]

Das Speichern von Instanzen des Structs Setlist in SQLite erfordert die Verwendung eines Wrapper-Libraries die eine einfachere Anbindung von SQLite Datenbanken in Swift ermöglicht, wie z.B FMDB. Hier ist ein Beispiel dafür, wie dies mit Swift und FMDB (OpenSoure Lib) erreicht werden kann:

import FMDB

struct Setlist {
    var title: String = "Default"
    var songs = [Song]()
    var id: Int32?
    mutating func addSong(title: String, frequency: Float){
        print("Setlist::addSong")
        songs.append(Song(title:title, frequency: frequency))
    }
}

struct Song {
    let title: String
    let frequency: Float
}

let databaseQueue = FMDatabaseQueue(url: try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("db.sqlite"))

func createTable() {
    databaseQueue.inDatabase { db in
        do {
            try db.executeUpdate("CREATE TABLE Setlist (id INTEGER PRIMARY KEY, title TEXT);", values: nil)
            try db.executeUpdate("CREATE TABLE Song (id INTEGER PRIMARY KEY, title TEXT, frequency REAL, setlist_id INTEGER, FOREIGN KEY(setlist_id) REFERENCES Setlist(id));", values: nil)
        } catch {
            print(error)
        }
    }
}

// To Save
func saveSetlist(_ setlist: Setlist) {
    databaseQueue.inDatabase { db in
        do {
            try db.executeUpdate("INSERT INTO Setlist (title) VALUES (?);", values: [setlist.title])
            setlist.id = db.lastInsertRowId
            for song in setlist.songs {
                try db.executeUpdate("INSERT INTO Song (title, frequency, setlist_id) VALUES (?, ?, ?);", values: [song.title, song.frequency,setlist.id])
            }
        } catch {
            print(error)
        }
    }
}

// To Retrive
func fetchSetlist(with id: Int32) -> Setlist? {
    var setlist: Setlist?
    databaseQueue.inDatabase { db in
        do {
            let resultSetlist = try db.executeQuery("SELECT * FROM Setlist WHERE id = ?", values: [id])
            if resultSetlist.next() {
                setlist = Setlist(title: resultSetlist.string(forColumn: "title")!)
                setlist!.id = id
                let resultSongs = try db.executeQuery("SELECT * FROM Song WHERE setlist_id = ?", values: [id])
                while resultSongs.next() {
                    let song = Song(title: resultSongs.string(forColumn: "title")!,frequency: resultSongs.double(forColumn: "frequency"))
                    setlist!.songs.append(song)
                }
            }
            resultSetlist.close()
         } catch {
             print(error)
         }
    }
    return setlist
}

Dieses Beispiel verwendet FMDB, um eine Verbindung zur SQLite-Datenbank herzustellen und Abfragen auszuführen, um Instanzen des Structs Setlist zu speichern und abzurufen. Beachten Sie, dass die Beispielstrukturen und die Datenbanktabellen beide eine ID-Eigenschaft haben, um die Beziehungen zwischen Setlist und Song zu verwalten. Es gibt auch andere Bibliotheken wie SQLite.swift die auch SQLite in Swift erleichtern. Ich empfehle Ihnen, sich mit den Best Practices für die Verwendung von SQLite in iOS-Apps vertraut zu machen, um sicherzustellen, dass Ihre Anwendung sicher und performant ist.