如何同时从两个 JSON 字段中过滤(SwiftUI)

How to filter from two JSON fields at the same time (SwiftUI)

我正在尝试根据系统语言同时过滤来自两个JSON字段的数据:此时,系统语言识别似乎起作用(因为根据系统语言出现不同的元素), 但由于某些原因,我无法找到执行我想做的事情的确切代码...

正如您从代码中看到的那样,我首先尝试过滤特定单词(“意大利语”或“英语”)的“数据”字段,然后是“自动”字段以对各种信息进行分类。 .但结果并不好:有时我在列表中看到重复的相同信息,其他时候我只看到从“数据”字段而不是从“autore”字段过滤的信息...

所以,总而言之,我想获得的结果如下:如果系统语言是意大利语,则所有 JSON 在“数据”字段中包含关键字“意大利语”的数据必须是先过滤,再根据“autore”字段包含的具体关键字进一步过滤;另一方面,如果系统语言不是意大利语(而是任何其他语言),则必须首先过滤“数据”字段中包含关键字“english”的所有 JSON 数据,然后 - 如前一个案例 - 根据“autore”字段中包含的特定关键字进一步过滤。

你有什么建议吗?因为我认为我离确切的代码不是很远……或者可能不是:) 谢谢!

这是 SwiftUI 代码:

import SwiftUI
import URLImage

struct HistoryView: View {
    
    @ObservedObject var dm: DownloadManager
    let sysLanguage = NSLocale.current.languageCode
    
    var body: some View {
        if sysLanguage == "it" {
            List {
                ForEach(dm.JSON.filter {
                    [=11=].data == "italiano"
                }) { busso in
                    ForEach(dm.JSON.filter {
                        [=11=].autore == "storia"
                    }) { busso in
                        NavigationLink(
                            destination: DetailView(busso: busso)) {
                            HStack {
                                URLImage(URL(string: busso.fotoUrl) ?? furl)
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                Text(busso.titolo)
                                    .font(.headline)
                                Spacer().layoutPriority(-0.1)
                            }
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .frame(height: 50)
                        }
                    }
                }
            }
            .navigationTitle(Text("Storia di Busso"))
            .navigationBarTitleDisplayMode(.large)
        } else {
            List {
                ForEach(dm.JSON.filter {
                    [=11=].autore == "storia"
                }) { busso in
                    ForEach(dm.JSON.filter {
                        [=11=].data == "english"
                    }) { busso in
                        NavigationLink(
                            destination: DetailView(busso: busso)) {
                            HStack {
                                URLImage(URL(string: busso.fotoUrl) ?? furl)
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                Text(busso.titolo)
                                    .font(.headline)
                                Spacer().layoutPriority(-0.1)
                            }
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .frame(height: 50)
                        }
                    }
                }
            }
            .navigationTitle(Text("Storia di Busso"))
            .navigationBarTitleDisplayMode(.large)
        }
    }
}

struct HistoryView_Previews: PreviewProvider {
    static var previews: some View {
        HistoryView(dm: DownloadManager())
    }
}

这是 JSON 文件:

[
    {
        "id": "8",
        "titolo": "View",
        "autore": "galleria",
        "testo": "",
        "data": "english",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-13 22:55:57",
        "foto": "foto\/WP_20161110_001.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/WP_20161110_001.jpg"
    },
    {
        "id": "7",
        "titolo": "Storia di Busso",
        "autore": "storia",
        "testo": "Testo di prova",
        "data": "italiano",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-10 21:11:03",
        "foto": "foto\/1a3e733334ec8948b0328af4e5b7288a.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/1a3e733334ec8948b0328af4e5b7288a.jpg"
    },
    {
        "id": "6",
        "titolo": "Test 2",
        "autore": "ricette",
        "testo": "",
        "data": "english",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-08 10:49:56",
        "foto": "foto\/test_2.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/test_2.jpg"
    },
    {
        "id": "5",
        "titolo": "Test",
        "autore": "eventi",
        "testo": "",
        "data": "english",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-08 10:47:53",
        "foto": "foto\/coastal-wash-web.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/coastal-wash-web.jpg"
    },
    {
        "id": "4",
        "titolo": "Immagine di prova",
        "autore": "luoghi",
        "testo": "",
        "data": "italiano",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-08 10:24:46",
        "foto": "foto\/unnamed.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/unnamed.jpg"
    },
    {
        "id": "3",
        "titolo": "Panorama",
        "autore": "galleria",
        "testo": "",
        "data": "italiano",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-07 11:21:53",
        "foto": "foto\/WP_20161110_001.jpg",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/WP_20161110_001.jpg"
    },
    {
        "id": "2",
        "titolo": "Comune di Busso",
        "autore": "contatti",
        "testo": "Indirizzo, telefono, mail, altri dati da inserire",
        "data": "italiano",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-01 19:33:56",
        "foto": "foto\/DSCN0914.JPG",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/DSCN0914.JPG"
    },
    {
        "id": "1",
        "titolo": "Chiesa",
        "autore": "commercio",
        "testo": "Testo di prova, abbastanza lungo per verificare l'impaginazione e correggere eventuali errori.",
        "data": "english",
        "extra1": "",
        "extra2": "",
        "creazione": "2021-01-01 19:32:02",
        "foto": "foto\/CAM_0044.JPG",
        "fotoUrl": "http:\/\/geniuspointfrezza.altervista.org\/foto\/CAM_0044.JPG"
    }
]

下载管理器代码如下:

import SwiftUI
import Combine

class DownloadManager: ObservableObject {

    @Published var JSON: [BussoModel] = []
    @Published var searchText: String = "" {
             didSet {
                self.searchResults = self.JSON.filter { [=13=].titolo.contains(self.searchText) }
             }
        }
        @Published var searchResults: [BussoModel] = []

    init() {
        let url = URL(string: "https://geniuspointfrezza.altervista.org/index.php?json=1")!

        URLSession.shared.dataTask(with: url) {(data, response, error) in
            do {
                if let bussoData = data {

                    let decodedData = try JSONDecoder().decode([BussoModel].self, from: bussoData)
                    DispatchQueue.main.async {
                        self.JSON = decodedData
                    }
                } else {
                    print("No data")
                }
            } catch {
                print(error)
            }
        }.resume()
    }
}

根据您的评论,我相信这就是您想要做的(除非我误解了什么)。我从代码中删除了 URL 图片,因此您必须将其添加回来。

几个注意事项:

  • 尝试在 DownloadManager 中进行所有过滤和数据管理。我添加了一个过滤器函数,它在数据下载时以及视图初始化时调用。
  • 尽量避免将字符串硬编码到您的代码中。我创建了一个将处理“英语”和“意大利语”过滤器的语言枚举。
  • 如果您 运行 在代码中复制了整个部分(例如在 post 中您重写了“it”和“else”的视图),那么肯定有更好的方法。

.

import SwiftUI
//import URLImage

struct HistoryView: View {
    
    @ObservedObject var dm: DownloadManager
    let title: String
    
    init(dm: DownloadManager, autore: String) {
        self.dm = dm
        dm.filter(autore: autore)
        self.title = "\(autore)".capitalized + " di Busso"
    }
        
    var body: some View {
        List {
            if !dm.searchResults.isEmpty && !dm.isLoading {
                ForEach(dm.searchResults) { busso in
                    NavigationLink(
                        destination: Text(busso.titolo)) {
                        HStack {
                            Text(busso.fotoUrl)
                            Text(busso.titolo)
                                .font(.headline)
                            Spacer(minLength: 0)
                        }
                        .frame(maxWidth: .infinity)
                        .frame(height: 50)
                    }
                }
            } else if dm.isLoading {
                ProgressView()
            } else {
                Text("No results.")
            }
        }
        .navigationTitle(title)
    }
}

struct HistoryView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            HistoryView(dm: DownloadManager(), autore: "galleria")
        }
    }
}


import SwiftUI
import Combine

class DownloadManager: ObservableObject {

    @Published private(set) var JSON: [BussoModel] = []
    @Published private(set) var isLoading: Bool = true

    @Published private(set) var searchAutore: String?
    @Published private(set) var searchResults: [BussoModel] = []
    
    let language: Language
    
    enum Language: String {
        case italian
        case english
    }

    init() {
        language = NSLocale.current.languageCode == "it" ? .italian : .english
        getData()
    }
    
    private func getData() {
        let url = URL(string: "https://geniuspointfrezza.altervista.org/index.php?json=1")!

        URLSession.shared.dataTask(with: url) {(data, response, error) in
            do {
                if let bussoData = data {
                    let decodedData = try JSONDecoder().decode([BussoModel].self, from: bussoData)
                    DispatchQueue.main.async {
                        self.JSON = decodedData
                        self.isLoading = false
                        self.filter(autore: self.searchAutore)
                    }
                } else {
                    print("No data")
                    self.isLoading = false
                }
            } catch {
                print(error)
                self.isLoading = false
            }
        }.resume()
    }
    
    func filter(autore: String?) {
        searchAutore = autore
        searchResults = JSON.filter({ (bussoModel) -> Bool in
            return bussoModel.data == language.rawValue && (bussoModel.autore == searchAutore)
        })
    }
}

struct BussoModel: Codable, Identifiable {
    let id: String
    let titolo: String
    let autore: String
    let testo: String
    let data: String
    let extra1: String
    let extra2: String
    let creazione: String
    let foto: String
    let fotoUrl: String
}