I am able to update the favorite list in the favorite section , but only after i restart the app, i have multiple answers suggesting to add @ObservedObject var asset: Artists etc and also adding the managed obbject context, i tried all, but the Favorite section will not update on coredata change , can any one kindly suggest a way out of this, below is the code of the file where i am hoping to see the Favorites being added and shown after coredata update but currently this view is getting updated only after i restart the app.
The code has been divided in sections where SongCell, shows each cell and its play button further extracted . An image is also shown of when i reload the app , to see what i want in Favorites section.Thanks.
[![enter image description here][1]][1]
import Foundation
import SwiftUI
import Combine
import AVFoundation
struct Favorites: View {
@ObservedObject var favListVM = FavoriteListVM()
@ObservedObject var repo = FavoriteRepository()
@Binding var favListVM1: FavoriteListVM
var body: some View {
VStack {
NavigationView {
List {
ForEach(favListVM.favCellVMs) {
songCellVM in
SongCell(isVisible: $favListVM.isVisible, favCellVM: songCellVM, selectedSong: $favListVM.selectedSong, favListVM1: $favListVM1, isLoved: favListVM.isFavorite ?? false)
}
}
.navigationTitle("Favorites")
.font(.subheadline)
}
if favListVM.isVisible {
HStack(alignment: .bottom){
Image(uiImage: UIImage(data: favListVM.selectedSong?.artistImage ?? Data()) ?? UIImage())
.resizable()
.frame(width: 50, height: 50, alignment: .leading)
.scaledToFit()
.cornerRadius(10)
Spacer()
VStack {
Text(favListVM.selectedSong?.songname ?? " ")
Text(favListVM.selectedSong?.artistname ?? " ")
}
ExtractedView(isVisible: $favListVM.isVisible, selectedSong: $favListVM.selectedSong, favoriteListVM2: $favListVM1, favCellVM: FavoriteCellVM(song: Song(album: favListVM.selectedSong?.album ?? "no album found", artistImage: favListVM.selectedSong?.artistImage, artistname: favListVM.selectedSong?.artistname ?? "unknown", genre: favListVM.selectedSong?.genre, songMp3: favListVM.selectedSong?.songMp3, songname: favListVM.selectedSong?.songname ?? "no songs found", id: favListVM.selectedSong?.id ?? UUID())))
}
}
}
}
struct SongCell: View {
@Binding var isVisible: Bool
@ObservedObject var favCellVM: FavoriteCellVM
@State var playButton: Bool = false
@Binding var selectedSong: Song?
@Binding var favListVM1: FavoriteListVM
var isSelected: Bool { favCellVM.song.id == selectedSong?.id }
@Environment(\.managedObjectContext) var managedObjectContext
@State var isLoved:Bool
@FetchRequest(entity: Artists.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Artists.artistname, ascending: true)]) var artists: FetchedResults<Artists>
var onCommit: () -> () = { }
var body: some View {
HStack {
let result = artists.filter { artist in
artist.id == favCellVM.song.id
}
Image(uiImage: UIImage(data: favCellVM.song.artistImage ?? Data()) ?? UIImage())
.resizable()
.frame(width: 70, height: 70, alignment: .center)
.scaledToFit()
.cornerRadius(20)
Spacer()
Text(favCellVM.song.artistname)
Button(action: {
print(favCellVM.song.id!)
print(result[0].id!)
if (result[0].isFavorite == nil){
result[0].isFavorite = true
}
else if(result[0].isFavorite == false) {
result[0].isFavorite = true
}
else {
result[0].isFavorite = false
}
do {
try managedObjectContext.save()
print("done")
print(result)
}
catch {
print("\(error.localizedDescription)")
}
}) { Image(systemName: result[0].isFavorite == true ? "suit.heart.fill" : "suit.heart")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
//--
ExtractedView(isVisible: $isVisible, selectedSong: $selectedSong, favoriteListVM2: $favListVM1, favCellVM: favCellVM)
}
}
}
struct ExtractedView: View {
@Binding var isVisible: Bool
@Binding var selectedSong: Song?
@Binding var favoriteListVM2: FavoriteListVM
@ObservedObject var favCellVM: FavoriteCellVM
var isSelected: Bool { favCellVM.song.id == selectedSong?.id }
var body: some View {
Button(action: {
print(isSelected)
isVisible.toggle()
if isSelected {
selectedSong = nil
favoriteListVM2.audioPlayer?.stop()
} else {
selectedSong = favCellVM.song
isVisible = true
do {
favoriteListVM2.audioPlayer?.stop()
favoriteListVM2.audioPlayer = try AVAudioPlayer(data: favCellVM.song.songMp3!)
favoriteListVM2.audioPlayer?.prepareToPlay()
favoriteListVM2.audioPlayer?.play()
} catch let error {
print("\(error.localizedDescription)")
}
}
}){ Image(systemName: isSelected ? "pause.fill" : "play.fill")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
}
}
}
//Updated code after loremipsum answer
import Foundation
import SwiftUI
import Combine
import AVFoundation
struct Favorites: View {
// @ObservedObject var songsListVM = SongListVM()
// @ObservedObject var favListVM = FavoriteListVM()
// @StateObject var favListVM: FavoriteListVM
@StateObject var repo = FavoriteRepository()
@ObservedObject var favListVM1: FavoriteListVM
var body: some View {
VStack {
NavigationView {
List {
ForEach(favListVM1.favCellVMs) {
songCellVM in
// SongCell(isVisible: $favListVM.isVisible , songCellVM: songCellVM, selectedSong: $favListVM.selectedSong, songsListVM1: $favListVM1)
SongCell(isVisible: $favListVM1.isVisible, favCellVM: songCellVM, selectedSong: $favListVM1.selectedSong, isLoved: favListVM1.isFavorite ?? false)
}
}
.navigationTitle("Favorites")
.font(.subheadline)
}
//--
//--
if favListVM1.isVisible {
HStack(alignment: .bottom){
Image(uiImage: UIImage(data: favListVM1.selectedSong?.artistImage ?? Data()) ?? UIImage())
.resizable()
.frame(width: 50, height: 50, alignment: .leading)
.scaledToFit()
.cornerRadius(10)
Spacer()
VStack {
Text(favListVM1.selectedSong?.songname ?? " ")
Text(favListVM1.selectedSong?.artistname ?? " ")
}
ExtractedView(isVisible: $favListVM1.isVisible, selectedSong: $favListVM1.selectedSong, favoriteListVM2: favListVM1, favCellVM: FavoriteCellVM(song: Song(album: favListVM1.selectedSong?.album ?? "no album found", artistImage: favListVM1.selectedSong?.artistImage, artistname: favListVM1.selectedSong?.artistname ?? "unknown", genre: favListVM1.selectedSong?.genre, songMp3: favListVM1.selectedSong?.songMp3, songname: favListVM1.selectedSong?.songname ?? "no songs found", id: favListVM1.selectedSong?.id ?? UUID())))
}
}
}
}
struct SongCell: View {
@Binding var isVisible: Bool
@ObservedObject var favCellVM: FavoriteCellVM
@State var playButton: Bool = false
@Binding var selectedSong: Song?
// @Binding var favListVM1: FavoriteListVM
var isSelected: Bool { favCellVM.song.id == selectedSong?.id }
@Environment(\.managedObjectContext) var managedObjectContext
@State var isLoved:Bool
@FetchRequest(entity: Artists.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Artists.artistname, ascending: true)]) var artists: FetchedResults<Artists>
var onCommit: () -> () = { }
var body: some View {
HStack {
let result = artists.filter { artist in
artist.id == favCellVM.song.id
}
Image(uiImage: UIImage(data: favCellVM.song.artistImage ?? Data()) ?? UIImage())
.resizable()
.frame(width: 70, height: 70, alignment: .center)
.scaledToFit()
.cornerRadius(20)
Spacer()
Text(favCellVM.song.artistname)
Button(action: {
print(favCellVM.song.id!)
print(result[0].id!)
if (result[0].isFavorite == nil){
result[0].isFavorite = true
}
else if(result[0].isFavorite == false) {
result[0].isFavorite = true
}
else {
result[0].isFavorite = false
}
do {
try managedObjectContext.save()
print("done")
// print(result)
}
catch {
print("\(error.localizedDescription)")
}
}) { Image(systemName: result[0].isFavorite == true ? "suit.heart.fill" : "suit.heart")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
//--
ExtractedView(isVisible: $isVisible, selectedSong: $selectedSong, favoriteListVM2: favCellVM, favCellVM: favCellVM)
}
}
}
struct ExtractedView: View {
@Binding var isVisible: Bool
@Binding var selectedSong: Song?
@ObservedObject var favoriteListVM2: FavoriteListVM
@ObservedObject var favCellVM: FavoriteCellVM
var isSelected: Bool { favCellVM.song.id == selectedSong?.id }
var body: some View {
Button(action: {
print(isSelected)
isVisible.toggle()
if isSelected {
selectedSong = nil
favoriteListVM2.audioPlayer?.stop()
} else {
selectedSong = favCellVM.song
isVisible = true
do {
favoriteListVM2.audioPlayer?.stop()
favoriteListVM2.audioPlayer = try AVAudioPlayer(data: favCellVM.song.songMp3!)
favoriteListVM2.audioPlayer?.prepareToPlay()
favoriteListVM2.audioPlayer?.play()
} catch let error {
print("\(error.localizedDescription)")
}
}
}){ Image(systemName: isSelected ? "pause.fill" : "play.fill")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
}
}
}
//Repository for favorite
import Foundation
import SwiftUI
import CoreData
import AVFoundation
import Combine
class FavoriteRepository: ObservableObject, Identifiable {
@Published var song = [Song]()
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Artists.entity(), sortDescriptors: []) var artists1: FetchedResults<Artists>
init(){
loadData()
}
func loadData() {
let context = PersistenceManager.shared.container.viewContext
let fetchRequest: NSFetchRequest<Artists>
fetchRequest = Artists.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "isFavorite == %@", NSNumber(value: true))
let objects = try! context.fetch(fetchRequest)
song = objects.map {
artist in
Song(album: artist.album!, artistImage: artist.artistImage, artistname: artist.artistname!, genre: artist.genre, songMp3: artist.songMp3, songname: artist.songname!, id: artist.id)
}
}
}
//Update after advise from loremipsum to remove the ViewModel and repository
import Foundation
import SwiftUI
import Combine
import AVFoundation
struct Favorites: View {
@Binding var songLVM: SongListVM
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Artists.entity(), sortDescriptors: [], predicate: NSPredicate(format: "isFavorite == %@ ", NSNumber(value: true))) var artists1: FetchedResults<Artists>
var body: some View {
VStack {
NavigationView {
List {
ForEach(artists1) {
artist in
HStack {
Image(uiImage: UIImage(data: artist.artistImage ?? Data()) ?? UIImage())
.resizable()
.frame(width: 50, height: 50, alignment: .leading)
.scaledToFit()
.cornerRadius(10)
Spacer()
Text(artist.artistname ?? "no name")
Text(artist.songname ?? "no song name")
//-
Button(action: {
// print(artist.song.id!)
print(artist.id!)
if (artist.isFavorite == nil){
artist.isFavorite = true
}
else if(artist.isFavorite == false) {
artist.isFavorite = true
}
else {
artist.isFavorite = false
}
do {
try managedObjectContext.save()
print("done")
// print(result)
}
catch {
print("\(error.localizedDescription)")
}
}) { Image(systemName: artist.isFavorite == true ? "suit.heart.fill" : "suit.heart")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
// --
Button(action: {
do {
songLVM.audioPlayer?.stop()
songLVM.audioPlayer = try AVAudioPlayer(data: artist.songMp3!)
songLVM.audioPlayer?.prepareToPlay()
songLVM.audioPlayer?.play()
}
catch {
print("\(error.localizedDescription)")
}
}){ Image(systemName: false ? "pause.fill" : "play.fill")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
.padding()
}
.buttonStyle(PlainButtonStyle())
// --
}
}
}
.navigationTitle("Favorites")
.font(.subheadline)
}
}}}