简体   繁体   中英

NSOrderedSet and SwiftUI ForEach

I am trying to work with CoreData and SwiftUI and have two entities; Dog and Walk. It is a one-to-many relationship between Dog

public class Dog: NSManagedObject, Identifiable {
  @NSManaged public var name: String?
  @NSManaged public var walks: NSOrderedSet?
}

and Walk

public class Walk: NSManagedObject, Identifiable {
  @NSManaged public var date: Date?
  @NSManaged public var dog: Dog? 
}

The problem I am having is displaying all of the walks for a selected dog in a List. The following WalksView will display all current walks

struct WalksView: View {
@ObservedObject var dogWalksVM:DogWalkVM
var selectedIndex:Int
var body: some View {
    let currentDog = dogWalksVM.dogs[selectedIndex]
    return  List {
        if currentDog.walks == nil {
            EmptyView()
        } else {
            ForEach(0..<currentDog.walks!.count) { index in
                Text("Date \(self.walkDate(currentDog.walks![index] as! Walk))")
            }
        }
    }
    .navigationBarTitle(Text("Walks for \(dogWalksVM.dogs[selectedIndex].name ?? "")"), displayMode: .inline)
        .navigationBarItems(trailing: Button(action: {
            self.addWalk(for: currentDog)
        }, label: {
            Image(systemName: "plus")
        }))

}

func walkDate(_ walk:Walk) -> String{
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .medium
    guard let walkDate = walk.date as Date?  else { return ""}
    return dateFormatter.string(from: walkDate)

}

func addWalk(for currentDog:Dog) {
    self.dogWalksVM.addWalk(for: currentDog)

}
}

but when I add a new one, the app crashes with the following error:

 ForEach<Range<Int>, Int, Text> count (1) != its initial count (0).
 `ForEach(_:content:)` should only be used for *constant* data.
 Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and provide an explicit `id`!

If I try to do a ForEach on the walks like this:

 ForEach(Array(currentDog.walks!),id: \.self) { walk in
                Text("Date \(self.walkDate(walk))")
            }

I am told

Protocol type 'NSOrderedSet.Element' (aka 'Any') cannot conform to 'Hashable' because only concrete types can conform to protocols

The following should help you

 ForEach(Array(currentDog.walks!.set),id: \.self) { walk in
                Text("Date \(self.walkDate(walk))")
            }

As stated in this response , there's a better way to iterate over a NSOrderedSet. Array(my_nsorderedset.set) won't preserve the order!

Instead, use mynsorderedset.array as. [ContainedType].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM