import SwiftUI struct AlbumCollectionView: View { @Environment(\.managedObjectContext) var managedObjectContext @FetchRequest(entity: Photo.entity(), sortDescriptors: [ NSSortDescriptor(keyPath: \Photo.id, ascending: true) ] ) var photos: FetchedResults<Photo> @FetchRequest(entity: Album.entity(), sortDescriptors: [ NSSortDescriptor(keyPath: \Album.name, ascending: true) ] ) var albums: FetchedResults<Album> @State private var showingImagePicker = false @State private var showingPopover = false @State private var inputImage: UIImage? @State private var albumNameInput: String = "" let columns = [ GridItem(.adaptive(minimum: 150)) ] var body: some View { ScrollView { LazyVGrid(columns: columns, spacing: 20) { ForEach(albums) { album in NavigationLink(destination: AlbumView(album: album)) { VStack { Image(data: album.albumCoverImageData, placeholder: "No Image") .resizable() .aspectRatio(1, contentMode: .fill) .contextMenu(menuItems: { Button(action: { deleteAlbum(selectedAlbum: album) }) { Label("Remove", systemImage: "trash") } }) Text(album.name ?? "") } } } } .padding() .navigationBarTitle(Text("Albums")) .navigationBarItems(trailing: Menu { Button(action: { self.showingPopover = true }) { Label("Add Album", systemImage: "photo.on.rectangle.angled") } Button(action: { self.showingImagePicker = true }) { Label("Add Photo", systemImage: "photo") } } label: { Image(systemName: "plus") .popover(isPresented: $showingPopover, arrowEdge: .trailing ,content: { VStack { Text("New Album") TextField("Enter Album Name",text: $albumNameInput) .textFieldStyle(RoundedBorderTextFieldStyle()) Button("Submit"){ addAlbum(name: albumNameInput, albumCover: UIImage(named: "Image 1")!) albumNameInput = "" showingPopover = false } } .padding() }) } ) .sheet(isPresented: $showingImagePicker, onDismiss: loadImage) { ImagePicker(image: self.$inputImage) } } } func addAlbum(name: String, albumCover: UIImage) { let newAlbum = Album(context: managedObjectContext) newAlbum.id = UUID() newAlbum.name = name newAlbum.passwordProtected = false newAlbum.albumCoverImageData = albumCover.jpegData(compressionQuality: 1.0) saveContext() } func deleteAlbum(selectedAlbum: Album) { for album in albums { if selectedAlbum == album { self.managedObjectContext.delete(album) } } saveContext() } func loadImage() { guard let inputImage = inputImage else { return } addPhoto(image: inputImage) } func addPhoto(image: UIImage) { let newPhoto = Photo(context: managedObjectContext) newPhoto.id = UUID() newPhoto.imageData = image.jpegData(compressionQuality: 1.0) saveContext() } func saveContext() { do { try managedObjectContext.save() } catch { print("Error saving managed object context: \(error)") } } }