Reputation: 1216
I have a model which, for the sake of example, is a tag cloud and a model for items:
struct TagCloud: Identifiable, Hashable{
var id: Int
let tag: String
static func tagCloud() -> [TagCloud]{
return [ TagCloud(id: 01, tag:"Green"),
TagCloud(id: 02, tag:"Blue"),
TagCloud(id: 03, tag:"Red")]
}
}
struct TaggedItem: Identifiable, Hashable{
var id: Int
let tag: String
let item: String
static func taggedItems() -> [TaggedItem]{
return [ TaggedItem(id: 01, tag:"Green", item: "Tree"),
TaggedItem(id: 02, tag:"Blue", item: "Sky"),
TaggedItem(id: 03, tag:"Red", item: "Apple")...]
}
}
I have a class to 'contain' the currently selected items:
class SelectedItems: ObservableObject {
@Published var currentlySelectedItems:[TaggedItem] = []
func changeData(forTag tag: String ){
let currentSelection = TaggedItem. taggedItems()
let filteredList = cardCollection.filter { $0.tag == tag }
currentlySelectedItems = filteredList
}
}
In my parent view, I select one of the tags from the cloud:
struct ParentView: View {
let tagCloud = TagCloud.tagCloud()
@ObservedObject var currentSelection : TaggedItem = TaggedItem()
@State var navigationTag:Int? = nil
var body: some View {
NavigationLink(destination: ChildView(), tag: 1, selection: $tag) {
EmptyView()
}
VStack{
ScrollView(.horizontal, content: {
HStack(spacing: 20){
ForEach( self.tagCloud, id: \.self) { item in
VStack{
Button(action: {
self. currentSelection.changeData(forTag: item.tag )
self.navigationTag = 1
}){
Text(item.tag)
}.buttonStyle(PlainButtonStyle())
..
}
The child view contains the ObservedObject. As a side note, I have also set this as an EnvironmentObject.
struct ChildView: View {
@ObservedObject var currentItems : SelectedItems = SelectedItems()
var body: some View {
VStack{
ScrollView(.horizontal, content: {
HStack(spacing: 20){
ForEach( currentItems.currentlySelectedItems, id: \.self) { item in
...
The problem:
I tried a number of things with init(). I tried passing the selected tag to the child, and then doing the filtering within init() itself, but was stymied by the need to bind to a class. I read elsewhere to try having a second model which would be updated by the FIRST model in order to trigger a view refresh.
What is the correct way to create this filtered list via a parent view selection and make the list available in the child view?
Upvotes: 1
Views: 133
Reputation: 257493
This part should be rethink:
let tagCloud = TagCloud.tagCloud()
@ObservedObject var currentSelection : TaggedItem = TaggedItem()
^^ is a struct, it cannot be observed !!!
@ObservedObject
must be applied only to @ObservableObject
as you did for SelectedItems
, so probably another ObservableObject
view model wrapper around TaggedItem
is expected here.
Upvotes: 1