Datenbank Import + export

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

  • Datenbank Import + export

    Hallo zusammen,
    ich verwalte in meiner App eine Datenbank. Ich möchte der App gerne die Funktion zum Sport und Export der Datenbank hinzufügen. Der Export funktioniert soweit erstmal, es wird eine *.sqlite Datei erstellt. Nun habe ich beim Import das Problem, dass ich die Datei zwar im Fester sehe, ich kann jedoch keine Datei auswählen. Woran hängt? Muss ich der App den Zugriff noch extra in der Info erlauben? Ist mein Code unvollständig?
    Anbei der Code, wie ich die Funktion aktuell implementiert habe

    Quellcode

    1. // export funktion
    2. func exportDatabase(completion: @escaping (URL?) -> Void) {
    3. let context = persistentContainer.viewContext
    4. let storeCoordinator = persistentContainer.persistentStoreCoordinator
    5. guard let store = storeCoordinator.persistentStores.first else {
    6. completion(nil)
    7. return
    8. }
    9. let exportURL = FileManager.default.temporaryDirectory.appendingPathComponent("BookCatalog.sqlite")
    10. do {
    11. try storeCoordinator.migratePersistentStore(store, to: exportURL, options: nil, withType: NSSQLiteStoreType)
    12. completion(exportURL)
    13. } catch {
    14. print("Failed to export database: \(error)")
    15. completion(nil)
    16. }
    17. }
    18. // import funktion
    19. func importDatabase(from url: URL, completion: @escaping (Bool) -> Void) {
    20. let storeCoordinator = persistentContainer.persistentStoreCoordinator
    21. guard let store = storeCoordinator.persistentStores.first else {
    22. completion(false)
    23. return
    24. }
    25. do {
    26. try storeCoordinator.destroyPersistentStore(at: store.url!, ofType: NSSQLiteStoreType, options: nil)
    27. try storeCoordinator.replacePersistentStore(at: store.url!, destinationOptions: nil, withPersistentStoreFrom: url, sourceOptions: nil, ofType: NSSQLiteStoreType)
    28. try persistentContainer.viewContext.save()
    29. completion(true)
    30. } catch {
    31. print("Failed to import database: \(error)")
    32. completion(false)
    33. }
    34. }
    Alles anzeigen

    Und der Aufruf

    Quellcode

    1. // Export and Import Section
    2. DisclosureGroup {
    3. VStack {
    4. Button("Export Database") {
    5. databaseManager.exportDatabase { url in
    6. if let url = url {
    7. documentURL = url
    8. showDocumentExporter = true
    9. }
    10. }
    11. }
    12. .padding()
    13. .background(Color.blue)
    14. .foregroundColor(.white)
    15. .cornerRadius(8)
    16. .fileExporter(isPresented: $showDocumentExporter, document: documentURL.map { DatabaseDocument(url: $0) }, contentType: .database, defaultFilename: "BookCatalog") { result in
    17. switch result {
    18. case .success:
    19. print("Export successful")
    20. case .failure(let error):
    21. print("Export failed: \(error)")
    22. }
    23. }
    24. Button("Import Database") {
    25. showDocumentImporter = true
    26. }
    27. .padding()
    28. .background(Color.green)
    29. .foregroundColor(.white)
    30. .cornerRadius(8)
    31. .fileImporter(isPresented: $showDocumentImporter, allowedContentTypes: [.database], allowsMultipleSelection: false) { result in
    32. switch result {
    33. case .success(let urls):
    34. if let url = urls.first {
    35. databaseManager.importDatabase(from: url) { success in
    36. if success {
    37. showAlert = true
    38. } else {
    39. print("Import failed")
    40. }
    41. }
    42. }
    43. case .failure(let error):
    44. print("Import failed: \(error)")
    45. }
    46. }
    47. }
    48. }
    49. label: {
    50. Text("Export/Import Database")
    51. .foregroundColor(.blue)
    52. }
    53. }
    54. .padding()
    Alles anzeigen
  • Menslo schrieb:

    .fileImporter(isPresented: $showDocumentImporter, allowedContentTypes: [.database], allowsMultipleSelection: false) { result in
    Dein Problem dürfte im hier verwendeten UTType liegen: Ich vermute, dass die von Dir erstellte Datei nicht dem Content-Type public.database entspricht, der hier als einziger erlaubt ist - das könntest Du einmal mittels mdls prüfen. Im Zweifelsfall müsstest Du in der info.plist einen entsprechenden UTI definieren...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Neu

    Menslo schrieb:

    Kann ich steuern, welchen Content Type die Datei entspricht (Fundwie?)?
    Schau mal in den verlinkten Artikel bzgl. UTIs und deren Definition in der info.plist. Ich würde erst einmal den Content Type besagter Datei überprüfen ... dann weisst Du auch, welchen Du beim OpenPanel erlauben musst: Eventuell ist die Definition eines eigenen UTI gar nicht erforderlich.

    Eigentlich nichts, was ich nicht oben schon erwähnte ;)

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Neu

    Welche UTI ist es denn? Du exportierst nur welche, die Du selber "verantwortest" (meist proprietäre Dateiformate) - hier kaum der Fall. Eventuell reicht es schon, den Identifier nur in Deinem Aufruf des OpenPanels als akzeptierten Dateityp anzugeben. Sonst eben in der info.plist importieren.

    Der oben verlinkte Artikel führt Dich nach zwei Klicks zu Hintergrundmaterial, das Dir hilft:

    Apple schrieb:

    Define an exported type when your app is the canonical source of information for that type. For example, if your app uses its own proprietary document format, declare it as an exported type.
    Define an imported type if your app uses a type that another app defines, or if it’s a proprietary file format the system doesn’t declare. When importing a type from another app, don’t declare your own identifier; instead, use the same type identifier as the original.
    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Neu

    Die Überprüfung mit mdls ergibt

    Quellcode

    1. kMDItemContentTypeTree = (
    2. "public.item",
    3. "dyn.ah62d4rv4ge81g6pqrf4gn",
    4. "public.data"
    5. )
    Ich bin ein bisschen überfragt beim Hinzufügen des Arrays in der info, welche Werte ich dort angeben muss. Vor Allem bei den Additional document type Properties

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Menslo ()

  • Neu

    Menslo schrieb:

    Ich bin ein bisschen überfragt beim Hinzufügen des Arrays in der info, welche Werte ich dort angeben muss. Vor Allem bei den Additional document type Properties
    Geh' mal einen Schritt zurück:

    Du speicherst eine Datei, die Du wieder öffnen möchtest. Diese Datei hat nur eine sehr generische UTI (bzw. Konformität zu sehr allgemeinen Typen). Du hast also zwei Optionen:
    1. Du erlaubst beim Öffnen auch alle Dateien der UTIs "public.item" bzw. "public.data". Damit kann der Benutzer diverse Dateien selektieren, die eventuell gar keinen Sinn machen. Deine App muss unerwartete Dateiformate händeln - sollte sie aber eh.
    2. Du definierst einen eigenen UTI, entweder auf Basis der Dateierweiterung ".sqlite" oder einer eigenen, den Du in der info.plist exportierst. Diesen UTI kannst Du dann beim Open referenzieren. Hier findest Du die entsprechenden Keys erklärt - oder schau einmal in bestehende Apps.
    Ich würde pragmatisch zunächst den ersten Weg probieren - nur bei für die App essentiellen Dateitypen (z. B. Dokument-Bearbeitung, externes Öffnen etc.) sind eigene UTIs m. E. unumgänglich.

    Das Thema erfordert etwas Recherche und Testen, insbesondere wenn Konflikte mit exportierten UTIs anderer Apps auftreten - es lohnt sich aber, tiefer einzusteigen.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.