CoreData

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Hallo,

      ich habe eine Datenbank in welche ich Daten speichern kann.
      Das klappt wunderbar.

      Jetzt wollte ich das ganze um Bilder erweitern. Also nicht nur Strings/Ints speichern.

      Deshalb einfach meinen Button, der bisher keine Bilder speichern konnte erweitert.

      Vorher:

      Quellcode

      1. Button("Save")
      2. {
      3. let newCreature = Kreatur(context: moc)
      4. newCreature.id = UUID()
      5. newCreature.name = name
      6. newCreature.nameCN = nameCN
      7. newCreature.country = country
      8. newCreature.information = information
      9. newCreature.rating = Int16(rating)
      10. try? moc.save()
      11. dismiss()
      12. }
      Alles anzeigen



      Jetzt:


      Quellcode

      1. Button("Save")
      2. {
      3. let newCreature = Kreatur(context: moc)
      4. newCreature.id = UUID()
      5. newCreature.name = name
      6. newCreature.nameCN = nameCN
      7. newCreature.country = country
      8. newCreature.information = information
      9. newCreature.rating = Int16(rating)
      10. let jpegImageData = inputImage?.jpegData(compressionQuality: 1.0)
      11. let entityName = NSEntityDescription.entity(forEntityName: newCreature.picture, in: moc)!
      12. let image = NSManagedObject(entity: entityName, insertInto: moc)
      13. image.setValue(jpegImageData, forKeyPath: newCreature.picture)
      14. try? moc.save()
      15. dismiss()
      16. }
      Alles anzeigen

      In Zeile 11 zeigt er mir den Fehler: "Cannot vonvert value of type "Data?" to expected argument type "String""

      Aber genau diese Funktion sollte ja eigentlich mein Foto in verwertbare Daten wandeln.

      Ich hoffe Ihr könnt mir auf die Sprünge helfen, wie ich das Bild korrekt in Core Data abspeichern kann
    • Wenn du Bilder in der Datenbank speichern willst, sollte der Typ für das Feld Binary Data sein. Wie du das ganze dann von und für SwiftUI codierst und decodierst, ist zum Beispiel hier ganz gut beschriebene:

      blog.devgenius.io/saving-images-in-coredata-8739690d0520

      Generell würde ich es mir aber immer gut überlegen, ob Bilder in Datenbanken eine gute Idee sind. Damit wird die Datenbank schnell unnötig groß und in manchen Fälle ist es besser, die Bilder getrennt als Datei zu speichern und in den Datenbank nur die URL zum Bild zu hinterlegen.
      So Long, and Thanks for All the Fish.
    • Ich weiß nur nicht, warum Xcode mir sagt, dass meine Entität vom Typ String sei.

      Eine Entität kann so viel ich weiß keinen Typ haben und mein Attribut ist vom Typ Binary Data

      Ich habe im Augenblick keinen Schimmer, wo bei mir der Fehler liegen könnte.

      Hier nochmal der relevante Code:
      Zeile 13 wäre wichtig zu wissen

      Quellcode

      1. import CoreData
      2. import SwiftUI
      3. struct AddCreatureView: View
      4. {
      5. @Environment(\.managedObjectContext) var moc
      6. @Environment(\.dismiss) var dismiss
      7. @State private var name = ""
      8. @State private var nameCN = ""
      9. @State private var country = ""
      10. @State private var information = ""
      11. @State private var rating = 3
      12. //@State private var picture = muss hier eventuell doch ein Eintrag hin?
      13. @State private var countryIndex = 0
      14. @State private var image: Image?
      15. @State private var showingImagePicker = false
      16. @State private var inputImage: UIImage?
      17. let countries = ["Germany", "France", "Italy", "Spain", "Greece", "Baltic States", "Russia", "Eastern Europe", "Middle-East", "North America", "Central America", "South America", "China", "Japan", "Asia", "Oceania", "Unknown"]
      18. var body: some View
      19. {
      20. NavigationView
      21. {
      22. Form
      23. {
      24. Section
      25. {
      26. TextField("Name of the Creature", text: $name)
      27. TextField("Local Name of the Creature", text: $nameCN)
      28. }
      29. Section
      30. {
      31. TextEditor(text: $information)
      32. } header: {
      33. Text("Write down Creature information")
      34. }
      35. Picker("Country", selection: $country)
      36. {
      37. ForEach(countries, id: \.self)
      38. {
      39. Text($0)
      40. }
      41. }
      42. .pickerStyle(WheelPickerStyle())
      43. Section
      44. {
      45. Spacer()
      46. VStack(alignment: .center)
      47. {
      48. ZStack
      49. {
      50. Rectangle()
      51. .fill(.secondary)
      52. Text("Tap to select an image")
      53. .foregroundColor(.white)
      54. .font(.headline)
      55. image?
      56. .resizable()
      57. .scaledToFit()
      58. }
      59. .onTapGesture
      60. {
      61. showingImagePicker = true
      62. }
      63. }
      64. Spacer()
      65. }
      66. Section
      67. {
      68. VStack()
      69. {
      70. HStack
      71. {
      72. Spacer()
      73. RatingView(rating: $rating)
      74. Spacer()
      75. }
      76. }
      77. }
      78. Section
      79. {
      80. Button("Save")
      81. {
      82. let newCreature = Kreatur(context: moc)
      83. newCreature.id = UUID()
      84. newCreature.name = name
      85. newCreature.nameCN = nameCN
      86. newCreature.country = country
      87. newCreature.information = information
      88. newCreature.rating = Int16(rating)
      89. let jpegImageData = inputImage?.jpegData(compressionQuality: 1.0)
      90. let entityName = NSEntityDescription.entity(forEntityName: newCreature.picture, in: moc)!
      91. let image = NSManagedObject(entity: entityName, insertInto: moc)
      92. image.setValue(jpegImageData, forKeyPath: newCreature.picture)
      93. try? moc.save()
      94. dismiss()
      95. }
      96. }
      97. }
      98. .navigationTitle("Add Creature")
      99. .onChange(of: inputImage) { _ in loadImage() }
      100. .sheet(isPresented: $showingImagePicker)
      101. {
      102. ImagePicker(image: $inputImage)
      103. }
      104. }
      105. }
      106. func loadImage()
      107. {
      108. guard let inputImage = inputImage else { return }
      109. image = Image(uiImage: inputImage)
      110. }
      111. }
      Alles anzeigen
    • Kannst du mal einen Screenshot von deinem DataModel für Kreatur zeigen? Was hast du für die Entity im Bereich Codegen eingestellt? Wenn es dort auf Manual/None steht, kann es sein, dass du deine Kreature+CoreDataProperties.swift nicht aktualisiert hast und dort noch was und er Art wie @NSManaged public var image: String? drin steht?
      So Long, and Thanks for All the Fish.
    • Ok, also befindet sich das Bild bzw. die Bilddaten direkt in der Entity Kreatur.

      Dann kannst Du die Bilddaten natürlich direkt in Kreatur ablegen. ;)

      Quellcode

      1. Button("Save")
      2. {
      3. let newCreature = Kreatur(context: moc)
      4. newCreature.id = UUID()
      5. newCreature.name = name
      6. newCreature.nameCN = nameCN
      7. newCreature.country = country
      8. newCreature.information = information
      9. newCreature.rating = Int16(rating)
      10. let jpegImageData = inputImage?.jpegData(compressionQuality: 1.0)
      11. newCreature.picture = jpegImageData
      12. try? moc.save()
      13. dismiss()
      14. }
      Alles anzeigen
    • Babelfisch schrieb:

      Generell würde ich es mir aber immer gut überlegen, ob Bilder in Datenbanken eine gute Idee sind. Damit wird die Datenbank schnell unnötig groß und in manchen Fälle ist es besser, die Bilder getrennt als Datei zu speichern und in den Datenbank nur die URL zum Bild zu hinterlegen.

      Das stimmt. Wenn ich mich nicht irre, übernimmt CoreData mittlerweile sogar das Auslagern von größeren Dateien automatisch. Dazu muss man im Editor bei der entsprechenden Property lediglich die Checkbox "Allow external storage" aktivieren. Habe das bislang allerdings noch nicht selbst getestet.
    • Babelfisch schrieb:

      Generell würde ich es mir aber immer gut überlegen, ob Bilder in Datenbanken eine gute Idee sind. Damit wird die Datenbank schnell unnötig groß und in manchen Fälle ist es besser, die Bilder getrennt als Datei zu speichern und in den Datenbank nur die URL zum Bild zu hinterlegen.
      Wenn man die Bilder auslagert, z.B. Filesystem, dann hat man sozusagen zwei Datenbanken die unterschiedlich organisiert sind und eigentlich wird es dann komplizierter, da man zwei Systeme zu betreuen hat statt eins. Ich denke, dass hängt von der Datenbank and der Infrastruktur ab, wo man etwas ableget oder nicht.
    • manoh schrieb:

      Wenn man die Bilder auslagert, z.B. Filesystem, dann hat man sozusagen zwei Datenbanken die unterschiedlich organisiert sind und eigentlich wird es dann komplizierter, da man zwei Systeme zu betreuen hat statt eins. Ich denke, dass hängt von der Datenbank and der Infrastruktur ab, wo man etwas ableget oder nicht.
      Deshalb ja auch mein Einwand, dass man sich das gut überlegen muss. Viele Systeme beziehen ihre Daten so oder so über unterschiedliche Quelle wie Datenbanken, Nutzerverzeichnisse, das OS, externe Quelle, etc. pp. Da macht es dann keinen großen Unterschied mehr, ob Bilder auch noch getrennt gespeichert werden. Sinn macht es besonders da, wo bspw. Bilder auch mehrfach vorkommen können und mit der externen Speicherung Platz gespart werden kann. Bei kleinen eindeutigen Bilder wie bspw. einem Avatar-Bild in der Nutzerdatenbank würde ich es auch eher in der Datenbank speichern. Hier gibt es kein schwarz oder weiß und die Planung einer guten Daten(bank)-Struktur ist nicht einfach aber sehr wichtig.
      So Long, and Thanks for All the Fish.
    • Osxer schrieb:

      Das stimmt. Wenn ich mich nicht irre, übernimmt CoreData mittlerweile sogar das Auslagern von größeren Dateien automatisch. Dazu muss man im Editor bei der entsprechenden Property lediglich die Checkbox "Allow external storage" aktivieren. Habe das bislang allerdings noch nicht selbst getestet.
      Ich habs auch auch noch nicht getestet aber so, wie es hier beschrieben ist, sieht das wirklich nach einer guten Lösung aus.
      So Long, and Thanks for All the Fish.
    • Runshak schrieb:

      Wenn man das nachträglich aktiviert werden die bereits gespeicherten Bilder auch ausgelagert oder ist es besser die bisherigen Bilder zu löschen und neu anzulegen?
      Ich kann es nicht mit Sicherheit sagen aber nach Änderungen am Datenmodell muss man normalerweise immer eine Migration ausführen. Ob da eine automatische „Lightweight Migration“ ausreichend ist, weiß ich auch nicht.

      In meinem Core Data Buch von raywenderlich steht:

      raywenderlich schrieb:

      If you check the Allows External Storage option, Core Data automatically decides if it’s better to save the data to disk as a separate file or leave it in the SQLite database.

      Wenn die Daten also automatisch – vermutlich je nach Größe – mal in der DB und mal außerhalb gespeichert werden, hat man ja nicht so viel Einfluss darauf und vermutlich reicht dann auch eine einfacher Migration aus.
      So Long, and Thanks for All the Fish.