From 29c8101d22877d7c74ae8d93831fa8f670a2dae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dr=2E=20Julian-Steffen=20M=C3=BCller?= Date: Tue, 18 May 2021 17:29:23 +0200 Subject: [PATCH] Changed GameLibraryView and GameDetailView to new swiftui core data best practise. Fixed Import/Export of Library --- Zockerhoehle.xcodeproj/project.pbxproj | 4 - .../CDModel/Console+CoreDataClass.swift | 2 +- Zockerhoehle/CDModel/Game+CoreDataClass.swift | 38 ++--- .../CDModel/Game+CoreDataProperties.swift | 4 +- Zockerhoehle/Utils/LibraryImport.swift | 20 +-- Zockerhoehle/ViewModel/GameStore.swift | 5 +- Zockerhoehle/ViewModel/GameViewModel.swift | 146 ------------------ Zockerhoehle/Views/ConsoleLibraryView.swift | 83 +++++----- Zockerhoehle/Views/GameDetailView.swift | 112 +++++++------- Zockerhoehle/Views/SettingsView.swift | 29 ++-- .../Zockerhoehle.xcdatamodel/contents | 8 +- 11 files changed, 138 insertions(+), 313 deletions(-) delete mode 100644 Zockerhoehle/ViewModel/GameViewModel.swift diff --git a/Zockerhoehle.xcodeproj/project.pbxproj b/Zockerhoehle.xcodeproj/project.pbxproj index f201e41..624ca3e 100644 --- a/Zockerhoehle.xcodeproj/project.pbxproj +++ b/Zockerhoehle.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ B93C1B9D21496BFD0014FD6E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */; }; B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA321496BFE0014FD6E /* Assets.xcassets */; }; B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */; }; - B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60D022E5009700DD390F /* GameViewModel.swift */; }; B94112DE233A37DD00159AE4 /* DateConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112DD233A37DD00159AE4 /* DateConversion.swift */; }; B94112E0233A4EF800159AE4 /* GamePickupsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112DF233A4EF800159AE4 /* GamePickupsView.swift */; }; B94112E4233B597D00159AE4 /* ConsoleEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112E3233B597D00159AE4 /* ConsoleEditView.swift */; }; @@ -92,7 +91,6 @@ B93C1BA321496BFE0014FD6E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; B93C1BA821496BFE0014FD6E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryDetailView.swift; sourceTree = ""; }; - B93D60D022E5009700DD390F /* GameViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewModel.swift; sourceTree = ""; }; B94112DD233A37DD00159AE4 /* DateConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateConversion.swift; sourceTree = ""; }; B94112DF233A4EF800159AE4 /* GamePickupsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePickupsView.swift; sourceTree = ""; }; B94112E3233B597D00159AE4 /* ConsoleEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleEditView.swift; sourceTree = ""; }; @@ -249,7 +247,6 @@ B93D60CF22E5006F00DD390F /* ViewModel */ = { isa = PBXGroup; children = ( - B93D60D022E5009700DD390F /* GameViewModel.swift */, B9E2A078233B69D400EAEB14 /* GameSeriesViewModel.swift */, B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */, B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */, @@ -446,7 +443,6 @@ B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */, B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */, B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */, - B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */, B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */, B90E03EB238557D900E79643 /* LibraryImport.swift in Sources */, B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */, diff --git a/Zockerhoehle/CDModel/Console+CoreDataClass.swift b/Zockerhoehle/CDModel/Console+CoreDataClass.swift index 5445b02..ac32941 100644 --- a/Zockerhoehle/CDModel/Console+CoreDataClass.swift +++ b/Zockerhoehle/CDModel/Console+CoreDataClass.swift @@ -75,7 +75,7 @@ extension Console : Encodable { var gamesList : [String] = [] for game in games! { if let game = game as? Game { - gamesList.append(game.uuid!.uuidString) + gamesList.append(game.uuid.uuidString) } } try container.encode(gamesList, forKey: .games) diff --git a/Zockerhoehle/CDModel/Game+CoreDataClass.swift b/Zockerhoehle/CDModel/Game+CoreDataClass.swift index 903c4e7..fa98b6a 100644 --- a/Zockerhoehle/CDModel/Game+CoreDataClass.swift +++ b/Zockerhoehle/CDModel/Game+CoreDataClass.swift @@ -13,19 +13,7 @@ import SwiftUI @objc(Game) public class Game: NSManagedObject, Identifiable { - @nonobjc public class func fetchRequest(console : Console) -> NSFetchRequest { - let fetchRequest = NSFetchRequest(entityName: "Game") - fetchRequest.predicate = NSPredicate(format: "console == %@", console) - return fetchRequest - } - - @nonobjc public class func fetchRequest(gameSeries : GameSeries) -> NSFetchRequest { - let fetchRequest = NSFetchRequest(entityName: "Game") - fetchRequest.predicate = NSPredicate(format: "series == %@", gameSeries) - return fetchRequest - } - - public func addGameSeries(by objectIDStringified : String) { + public func addGameSeries(by objectIDStringified : String) { if let url = URL(string: objectIDStringified) { let persistentStoreCoordinator = CDManager.shared.persistentContainer.persistentStoreCoordinator @@ -44,16 +32,21 @@ public class Game: NSManagedObject, Identifiable { return gameACreated < gameBCreated } - init(context: NSManagedObjectContext) { - super.init(entity: Game.entity(), insertInto: context) + public var id : NSManagedObjectID { + get { + return self.objectID + } + } + + @objc + private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) { + super.init(entity: entity, insertInto: context) if self.createdAt == .none { self.createdAt = Date() } - } - @objc - private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) { - super.init(entity: entity, insertInto: context) + self.uuid = UUID() + print("Set UUID to \(self.uuid)") } } @@ -70,11 +63,12 @@ extension Game : Encodable { case inWishlist case console case gameSeries - case cover + case cover_icloud_path } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + print("UUID: \(self.uuid)") try container.encode(uuid, forKey: .uuid) try container.encode(name, forKey: .name) try container.encode(notes ?? "", forKey: .notes) @@ -84,13 +78,11 @@ extension Game : Encodable { try container.encode(publisher ?? "", forKey: .publisher) try container.encode(isFinished, forKey: .isFinished) try container.encode(inWishlist, forKey: .inWishlist) + try container.encode(cover_icloud_path ?? "", forKey: .cover_icloud_path) let consoleUUID : String = console?.uuid.uuidString ?? "" let gameSeriesUUID : String = series?.uuid.uuidString ?? "" try container.encode(consoleUUID, forKey: .console) try container.encode(gameSeriesUUID, forKey: .gameSeries) - - let imgBase64 = cover?.image?.pngData()?.base64EncodedString() ?? "" - try container.encode(imgBase64, forKey: .cover) } } diff --git a/Zockerhoehle/CDModel/Game+CoreDataProperties.swift b/Zockerhoehle/CDModel/Game+CoreDataProperties.swift index 9ec8f67..597a1eb 100644 --- a/Zockerhoehle/CDModel/Game+CoreDataProperties.swift +++ b/Zockerhoehle/CDModel/Game+CoreDataProperties.swift @@ -26,9 +26,9 @@ extension Game { @NSManaged public var name: String? @NSManaged public var notes: String? @NSManaged public var publisher: String? - @NSManaged public var uuid: UUID? + @NSManaged public var uuid: UUID + @NSManaged public var cover_icloud_path : String? @NSManaged public var console: Console? - @NSManaged public var cover: Cover? @NSManaged public var series: GameSeries? } diff --git a/Zockerhoehle/Utils/LibraryImport.swift b/Zockerhoehle/Utils/LibraryImport.swift index 4e15517..eb1951c 100644 --- a/Zockerhoehle/Utils/LibraryImport.swift +++ b/Zockerhoehle/Utils/LibraryImport.swift @@ -80,13 +80,9 @@ class LibraryImport { cdGame.inWishlist = game.inWishlist cdGame.isFinished = game.isFinished cdGame.lentTo = game.lentTo + cdGame.cover_icloud_path = game.cover_icloud_path //TODO: cdGame.createdAt = game.createdAt. - let cdCover = Cover(context: CDManager.shared.viewContext) - cdCover.image = game.cover - cdCover.game = cdGame - cdGame.cover = cdCover - cdConsole.addToGames(cdGame) cdGame.console = cdConsole print("Imported: \(cdGame.name) for \(cdConsole.name)") @@ -152,7 +148,7 @@ class LibraryImport { for console in library.consoles { let cdConsole = makeCDConsole(from: console) - print("CONSOLE: \(cdConsole.name) with \(console.games.count) games") + print("CONSOLE: \(cdConsole.name ?? "n/a") with \(console.games.count) games") for uuid in console.games { if let game = library.games.first(where: {$0.uuid == uuid}) { @@ -204,7 +200,7 @@ struct BHLGame : Decodable { let publisher : String? let console : UUID? let series : UUID? - let cover : UIImage? + let cover_icloud_path : String? enum CodingKeys: String, CodingKey { case uuid @@ -218,7 +214,7 @@ struct BHLGame : Decodable { case publisher case console case series - case cover + case cover_icloud_path } init(from decoder: Decoder) throws { @@ -232,16 +228,10 @@ struct BHLGame : Decodable { notes = try container.decode(String?.self, forKey: .notes) createdAt = try container.decode(String?.self, forKey: .notes) publisher = try container.decode(String?.self, forKey: .publisher) + cover_icloud_path = try container.decode(String?.self, forKey: .cover_icloud_path) console = try container.decode(UUID?.self, forKey: .console) series = try container.decode(UUID?.self, forKey: .console) - - if let coverBase64 = try container.decode(String?.self, forKey: .cover), - let coverData = Data(base64Encoded: coverBase64) { - cover = UIImage(data: coverData) - }else { - cover = .none - } } } diff --git a/Zockerhoehle/ViewModel/GameStore.swift b/Zockerhoehle/ViewModel/GameStore.swift index dc9002f..0b435f0 100644 --- a/Zockerhoehle/ViewModel/GameStore.swift +++ b/Zockerhoehle/ViewModel/GameStore.swift @@ -49,13 +49,14 @@ class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate lazy var fetchResultsController : NSFetchedResultsController = { var gamesFetch : NSFetchRequest = Game.fetchRequest() - if let console = consoleFilter { + + /*if let console = consoleFilter { gamesFetch = Game.fetchRequest(console: console) }else if let gameSeries = gameSeriesFilter { gamesFetch = Game.fetchRequest(gameSeries: gameSeries) }else { print("No filter: fetch Limit: \(self.fetchLimit)") - } + }*/ gamesFetch.fetchLimit = self.fetchLimit gamesFetch.sortDescriptors = self.sortDescriptors diff --git a/Zockerhoehle/ViewModel/GameViewModel.swift b/Zockerhoehle/ViewModel/GameViewModel.swift deleted file mode 100644 index 46dc9d3..0000000 --- a/Zockerhoehle/ViewModel/GameViewModel.swift +++ /dev/null @@ -1,146 +0,0 @@ -// -// GameViewModel.swift -// Zockerhoehle -// -// Created by Julian-Steffen Müller on 21.07.19. -// Copyright © 2019 Julian-Steffen Müller. All rights reserved. -// - -import Foundation -import SwiftUI -import Combine -import CoreData -import UIKit - -class GameViewModel : ObservableObject { - var objectWillChange = ObservableObjectPublisher() - - private var game : Game? { - didSet { - guard let game = game else { return } - - self.name = game.name! - self.inWishlist = game.inWishlist - self.isDigital = game.isDigital - self.isFinished = game.isFinished - } - } - - var lentTo : String { - didSet { - guard let game = self.game else { return } - - if lentTo != "" { - game.lentTo = lentTo; - } - } - } - - var name : String { - didSet { - guard let game = self.game else { return } - - game.name = name - } - } - - var inWishlist : Bool { - didSet { - guard let game = self.game else { return } - - game.inWishlist = inWishlist - } - } - - var isDigital : Bool { - didSet { - guard let game = self.game else { return } - - game.isDigital = isDigital - } - } - - var isFinished : Bool { - didSet { - guard let game = self.game else { return } - - game.isFinished = isFinished - } - } - - var gameSeries : String { - willSet { - if newValue != "" , let game = self.game { - game.addGameSeries(by: newValue) - } - } - } - - var console : Console? { - get { - return self.game?.console - } - } - - var cover : UIImage? { - get { - if let coverImage = self.game?.cover?.image { - return coverImage - } - - return .none - } - - set { - if let game = self.game { - if let coverImage = newValue { - let newCover = Cover(context: CDManager.shared.viewContext) - newCover.game = game - newCover.image = coverImage - game.cover = newCover - } - } - } - } - - func removeGame() { - if let game = self.game { - CDManager.shared.viewContext.delete(game) - } - } - - var NSManagedObjectChangedObserver : AnyCancellable? = .none - - init(game : Game) { - self.game = game - - self.name = game.name! - self.inWishlist = game.inWishlist - self.isDigital = game.isDigital - self.isFinished = game.isFinished - self.gameSeries = game.series?.id ?? "" - self.lentTo = game.lentTo ?? "" - - self.NSManagedObjectChangedObserver = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).first().sink { notification in - - guard let game = self.game else { return } - guard let userInfo = notification.userInfo else { return } - - var managedObjectIsMatching = false - if let inserts = userInfo[NSInsertedObjectsKey] as? Set { - if inserts.contains(game) { managedObjectIsMatching = true } - } - if let updates = userInfo[NSUpdatedObjectsKey] as? Set { - if updates.contains(game) { managedObjectIsMatching = true } - } - if let deletes = userInfo[NSDeletedObjectsKey] as? Set { - if deletes.contains(game) { managedObjectIsMatching = true } - } - - if managedObjectIsMatching { - self.objectWillChange.send() - print("GameViewModel::NSMangedObjectChanged Update of \(game.name)") - } - } - } -} diff --git a/Zockerhoehle/Views/ConsoleLibraryView.swift b/Zockerhoehle/Views/ConsoleLibraryView.swift index 41ee9f1..842b794 100644 --- a/Zockerhoehle/Views/ConsoleLibraryView.swift +++ b/Zockerhoehle/Views/ConsoleLibraryView.swift @@ -43,7 +43,7 @@ struct ModalAddToConsoleLibrary : View { self.addAccessoryToLibrary() } self.presentationMode.wrappedValue.dismiss()}, - label: { Text("Add") }) + label: { Text("Fertig") }) .disabled(self.modalAddName.trimmingCharacters(in: .whitespacesAndNewlines) == "" ) } @@ -61,9 +61,9 @@ struct ModalAddToConsoleLibrary : View { }) } .font(.caption) - .navigationBarTitle(self.isVideogamesSelected ? Text("New Game") : Text("New Accessory")) + .navigationBarTitle(self.isVideogamesSelected ? Text("Spiel hinzufügen") : Text("Zubehör hinzufügen")) .navigationBarItems(leading: Button(action: { self.presentationMode.wrappedValue.dismiss() }, - label: {Text("Cancel")}), + label: {Text("Abbrechen")}), //Add Button is disabled if no name is entered trailing: addButton) .navigationViewStyle(StackNavigationViewStyle()) @@ -72,14 +72,27 @@ struct ModalAddToConsoleLibrary : View { } struct ConsoleLibraryView : View { - @State var isVideogamesSelected = true - var console : Console? - @ObservedObject var gameStore : GameStore - @ObservedObject var accessoryStore : AccessoryStore + @ObservedObject var console : Console + @Environment(\.managedObjectContext) private var viewContext + + var gamesFetchRequest: FetchRequest + var games: FetchedResults { gamesFetchRequest.wrappedValue } + + var accessoryFetchRequest: FetchRequest + var accessories: FetchedResults { accessoryFetchRequest.wrappedValue } + + @State var isVideogamesSelected = true @State var showWishlist = false @State var showAddToConsoleLibraryModal: Bool = false - @State var showLogoImagePicker = false + + init (console: Console) { + self.console = console + + self.gamesFetchRequest = FetchRequest(entity: Game.entity(), sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)], predicate: NSPredicate(format: "console == %@", console)) + + self.accessoryFetchRequest = FetchRequest(entity: Accessory.entity(), sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)], predicate: NSPredicate(format: "console == %@", console)) + } var body: some View { VStack { @@ -93,43 +106,32 @@ struct ConsoleLibraryView : View { Spacer() } if self.isVideogamesSelected { - List { - ForEach(gameStore.games.filter({$0.inWishlist == self.showWishlist})) { game in - NavigationLink(destination: GameDetailView(game: game)) { - HStack { - /*game.cover.map { - Image(uiImage: $0.image) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 75) - }*/ - - Text("\(game.name!)") - - if game.isDigital { - Image("digitalGame") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 15) - } + List(games.filter({$0.inWishlist == self.showWishlist})) { game in + NavigationLink(destination: GameDetailView(game: game)) { + HStack { + Text("\(game.name ?? "n/a")") + + if game.isDigital { + Image("digitalGame") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 15) } } } } }else { - List { - ForEach(accessoryStore.accessories.filter({$0.inWishlist == self.showWishlist})) { accessory in - NavigationLink(destination: AccessoryDetailView(accessoryVM: AccessoryViewModel(accessory: accessory))) { - Text("\(accessory.name)") - } + List(accessories.filter({$0.inWishlist == self.showWishlist})) {accessory in + NavigationLink(destination: AccessoryDetailView(accessoryVM: AccessoryViewModel(accessory: accessory))) { + Text("\(accessory.name)") } } } } - .navigationBarTitle(Text("\(self.console?.name ?? "N/A")"), displayMode: .automatic) + .navigationBarTitle(Text("\(self.console.name ?? "n/a")"), displayMode: .automatic) .navigationBarItems(trailing: HStack { - NavigationLink(destination: ConsoleEditView(console: self.console!)) { + NavigationLink(destination: ConsoleEditView(console: self.console)) { Image(systemName: "pencil.and.ellipsis.rectangle") } @@ -145,18 +147,7 @@ struct ConsoleLibraryView : View { .accentColor(self.showWishlist ? Color.red : Color.blue) }) .sheet(isPresented: $showAddToConsoleLibraryModal) { - if self.console != nil { - ModalAddToConsoleLibrary(modalAddToWishlist: self.showWishlist, isVideogamesSelected: true, console: self.console!) - }else{ - Text("Fehler: Keine Konsole übergeben") - } - + ModalAddToConsoleLibrary(modalAddToWishlist: self.showWishlist, isVideogamesSelected: self.isVideogamesSelected, console: self.console) } } - - init(console : Console?) { - self.console = console - self.gameStore = GameStore(console: console) - self.accessoryStore = AccessoryStore(console: console) - } } diff --git a/Zockerhoehle/Views/GameDetailView.swift b/Zockerhoehle/Views/GameDetailView.swift index 7e00e17..1b47857 100644 --- a/Zockerhoehle/Views/GameDetailView.swift +++ b/Zockerhoehle/Views/GameDetailView.swift @@ -9,7 +9,7 @@ import SwiftUI struct GameDetailView : View { - @ObservedObject var gameVM : GameViewModel + @ObservedObject var game : Game @State private var showDeleteAlert : Bool = false @State var hasFinishedDate : Bool = false @@ -18,83 +18,64 @@ struct GameDetailView : View { @EnvironmentObject var gameSeriesStore : GameSeriesStore @Environment(\.presentationMode) var presentationMode: Binding - - @State var showingPicker = false - - @State var image : Image? = nil - + @State var isImportingCover : Bool = false @State var isLent : Bool = false + let defaultImage = UIImage() + var gameSeriesPicker : some View { - Picker(selection: $gameVM.gameSeries, label: + Text("TODO GameSeries Picker") + /*Picker(selection: $game.gameSeries, label: Text("Spieleserie") , content: { Text("Keine").tag("") ForEach(gameSeriesStore.gameSeries) { gameSeries in Text("\(gameSeries.name)").tag(gameSeries.id) } - }) + })*/ } - var imageCoverSection : some View { - Section { - VStack{ - Button("Show image picker") { - self.showingPicker = true - } - - if self.gameVM.cover != nil { - Image(uiImage: self.gameVM.cover!) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 100) - } - } - } - } - - var body: some View { Form { Section { - TextField("Videogame name", text: $gameVM.name) + TextField("Videogame name", text: $game.name ?? "") //Gray color should indicate immutable data - Text("\(gameVM.console?.name ?? "No console")").foregroundColor(.gray) + Text("\(game.console?.name ?? "No console")").foregroundColor(.gray) - Toggle(isOn: $gameVM.isDigital, label: { + Toggle(isOn: $game.isDigital, label: { Text("Nur Digital") }) - Toggle(isOn: $gameVM.inWishlist, label: { + Toggle(isOn: $game.inWishlist, label: { Text("In Wunschliste") }) Toggle(isOn: $isLent, label: { Text("Verliehen?") - }).onReceive(gameVM.objectWillChange) { _ in - self.isLent = self.gameVM.lentTo != ""; + }).onReceive(game.objectWillChange) { _ in + self.isLent = self.game.lentTo != ""; }.onAppear() { - self.isLent = self.gameVM.lentTo != ""; + self.isLent = self.game.lentTo != ""; } if isLent { - TextField("Verliehen an", text: $gameVM.lentTo) + TextField("Verliehen an", text: $game.lentTo ?? "") } gameSeriesPicker - Toggle(isOn: $gameVM.isFinished , label: { + Toggle(isOn: $game.isFinished , label: { Text("Durchgezockt") }) - if gameVM.isFinished { + if game.isFinished { Toggle(isOn: $hasFinishedDate, label: { Text("Gibts ein Datum") }) } - if hasFinishedDate && gameVM.isFinished { + if hasFinishedDate && game.isFinished { DatePicker("Durchgezockt am", selection: $playthroughDate, in: ...Date(), @@ -102,23 +83,43 @@ struct GameDetailView : View { } } - imageCoverSection + Section { + VStack{ + Button("Neues Cover auswählen") { + self.isImportingCover = true + } + + Image(uiImage: ICloudManager.imageFrom(path: game.cover_icloud_path) ?? defaultImage) + .resizable() + .frame(width:100, height: 100) + } + } Section{ gameDeleteButton } } - .navigationBarTitle(Text("\(gameVM.name)"), displayMode: .automatic) - .sheet(isPresented: $showingPicker, - onDismiss: { - // do whatever you need here - }, content: { - ImagePicker.shared.view - }) - .onReceive(ImagePicker.shared.objectWillChange) { image in - if let image = image { - self.gameVM.cover = image + .navigationBarTitle(Text("\(game.name ?? "N/A")"), displayMode: .automatic) + .fileImporter( + isPresented: $isImportingCover, + allowedContentTypes: [.jpeg, .png], + allowsMultipleSelection: false + ) { result in + do { + let selectedFile : URL = try result.get().first! + + //It seems that isUbiquitousItem checks if the file is contained in the Apps iCloud folder + if (FileManager.default.isUbiquitousItem(at: selectedFile)) { + game.cover_icloud_path = ICloudManager.relativePathFrom(url: selectedFile) + + print("Selected Image in iCloud Path \(game.cover_icloud_path ?? "n/a")") + }else{ + Alert(title: Text("Falscher Ordner")) + print("Außerhalb \(selectedFile.relativeString)") + } + }catch{ + print("ConsoleAllView::ModalAddConsoleToLibrary Error getting result '\(result)'") } } } @@ -136,19 +137,12 @@ struct GameDetailView : View { }) .accentColor(.red) .alert(isPresented: $showDeleteAlert, content: { - Alert(title: Text("Aus Zockerhöhle entfernen"), message: Text("Willst du '\(self.gameVM.name)' wirklich aus der Zockerhöhle werfen?"), primaryButton: Alert.Button.destructive(Text("Ja!"), action: { - //self.presentationMode.value.dismiss() - self.gameVM.removeGame() + Alert(title: Text("Aus Zockerhöhle entfernen"), message: Text("Willst du '\(self.game.name ?? "n/a")' wirklich aus der Zockerhöhle werfen?"), primaryButton: Alert.Button.destructive(Text("Ja!"), action: { + + //TZOOOODOOOOOO + //self.gameVM.removeGame() }), secondaryButton: Alert.Button.cancel(Text("Lieber doch nicht"))) }) } - init(gameVM : GameViewModel?) { - self.gameVM = gameVM! - } - - init(game : Game) { - self.gameVM = GameViewModel(game: game) - } - } diff --git a/Zockerhoehle/Views/SettingsView.swift b/Zockerhoehle/Views/SettingsView.swift index 3170d52..f782db8 100644 --- a/Zockerhoehle/Views/SettingsView.swift +++ b/Zockerhoehle/Views/SettingsView.swift @@ -7,7 +7,7 @@ // import SwiftUI - +import CoreData //extension String: Identifiable { // public var id: String { // return self @@ -20,15 +20,24 @@ struct SettingsView: View { @State var importFiles : [String] = LibraryImport().backupFiles() func exportLibrary() { - let games = GameStore().games - let consoles = ConsoleStore().consoles - let gameSeries = GameSeriesStore().gameSeries - let accessories = AccessoryStore().accessories - - let libExport = LibraryExporter(games: games, consoles: consoles, gameSeries: gameSeries, accessories: accessories) - - libExport.export(name: Date().formattedInTimeZone()) - importFiles = LibraryImport().backupFiles() + do { + let gamesFR = NSFetchRequest(entityName: "Game") + let consolesFR = NSFetchRequest(entityName: "Console") + let gameSeriesFR = NSFetchRequest(entityName: "GameSeries") + let accessoriesFR = NSFetchRequest(entityName: "Accessory") + + let games = try CDManager.shared.viewContext.fetch(gamesFR) + let consoles = try CDManager.shared.viewContext.fetch(consolesFR) + let gameSeries = try CDManager.shared.viewContext.fetch(gameSeriesFR) + let accessories = try CDManager.shared.viewContext.fetch(accessoriesFR) + + let libExport = LibraryExporter(games: games, consoles: consoles, gameSeries: gameSeries, accessories: accessories) + + libExport.export(name: Date().formattedInTimeZone()) + importFiles = LibraryImport().backupFiles() + }catch { + print("ERROR during export") + } } var body: some View { diff --git a/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents b/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents index 687b784..d3279bc 100644 --- a/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents +++ b/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents @@ -23,10 +23,9 @@ - - + @@ -37,7 +36,6 @@ - @@ -59,8 +57,8 @@ - - + +