简体   繁体   中英

How do I filter my data displayed in my view?

My XCODE Swift VIEW code below displays a list of all Flavor Groups and Descriptors from my data. What I would like to do is filter the data to display all Flavor Groups and Descriptors except where isSeltzer is false.

I have tried using something like this in my View Model and then using iterating from the filtered array in my view but I can't get this to work:

let flavorsNoSeltzers = flavors.filter({ return $0.isSeltzer != false })

Here is example of my local JSON data:

    [
    {
        "id": "562811",
        "flavorGroup": "APRICOT",
        "name": "NATURAL AND ARTIFICIAL APRICOT FLAVOR",
        "isBeer": true,
        "isSeltzer": false,
        "isArtificial": true,
        "descriptors": ["FRUITY"],
        "keywords": ["juicy", "skunky", "peach", "floral", "slight green (sierra nevada pale ale)"]
    },
    {
        "id": "U39252",
        "flavorGroup": "BANANA",
        "name": "NATURAL BANANA FLAVORING",
        "isBeer": true,
        "isSeltzer": true,
        "isArtificial": false,
        "descriptors": [""],
        "keywords": ["missing"]
    },
    {
        "id": "681686",
        "flavorGroup": "WHITE CHOCOLATE",
        "name": "NATURAL WHITE CHOCOLATE FLAVOR WONF",
        "isBeer": true,
        "isSeltzer": true,
        "isArtificial": false,
        "descriptors": ["LACTONIC", "COCOA", "CREAMY"],
        "keywords": ["nutty", "milk chocolate", "french vanilla", "custard", "cakey"]
    }
]

Here is an example of my MODEL:

struct Flavor: Codable, Identifiable {
    enum CodingKeys: CodingKey {
        case id
        case flavorGroup
        case name
        case isBeer
        case isSeltzer
        case isArtificial
        case descriptors
        case keywords
    }
    let id, flavorGroup, name: String
    let isBeer, isSeltzer, isArtificial: Bool
    let descriptors, keywords: [String]
}

Here is an example of my VIEW MODEL:

class ReadData: ObservableObject  {
    @Published var flavors = [Flavor]()  
    init(){
        loadData()
    }
    func loadData()  {
        guard let url = Bundle.main.url(forResource: "flavors", withExtension: "json")
            else {
                print("Json file not found")
                return
            }
        let data = try? Data(contentsOf: url)
        let flavors = try? JSONDecoder().decode([Flavor].self, from: data!)
        self.flavors = flavors!
    }
}

Here is an example of my VIEW:

struct myView: View {
    @ObservedObject var flavorData = ReadData()
    var body: some View{
        List(flavorData.flavors){ flavor in
            VStack(alignment: .leading) {
                Text(flavor.flavorGroup)
                ForEach(flavor.descriptors, id: \.self) { descriptor in
                    if descriptor.isEmpty {
                        // do nothing
                    } else {
                        Text("- \(descriptor)")
                    }
                }
            }
        }
    }
}

A simplified working example that filters the list of Flavor objects and returns a new list with only Flavor objects where isSeltzer is true .

import Foundation

struct Flavor {
    let id: String
    let isSeltzer: Bool
}

let flavors = [Flavor(id: "First", isSeltzer: false), Flavor(id: "Second", isSeltzer: true), Flavor(id: "Third", isSeltzer: false)]
let flavorsSeltzersTrue = flavors.filter({ $0.isSeltzer })

print(flavorsSeltzersTrue) // Prints the flavors with isSeltzer == true

If you want the opposite (ie where isSeltzer is false ), you can simply change $0.isSeltzer in the closure to .$0.isSeltzer . Also, check out the documentation on the filter(_:) method.

If this doesn't fix your issue, then there's something else going on with your code.

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