【问题标题】:How to filter from two JSON fields at the same time (SwiftUI)如何同时过滤两个 JSON 字段(SwiftUI)
【发布时间】:2021-01-13 22:50:42
【问题描述】:

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

从代码中可以看出,我首先尝试为特定单词(“italiano”或“english”)过滤字段“data”,然后过滤字段“autore”以对各种信息进行分类......但是结果不好:有时我看到列表中重复了相同的信息,有时我只看到从“数据”字段过滤的信息,而不是从“autore”字段过滤的信息......

所以,综上所述,我想得到的结果是:如果系统语言是意大利语,那么“data”字段中包含关键字“italian”的所有JSON数据都必须先过滤,再过滤进一步基于“autore”字段中包含的特定关键字;另一方面,如果系统语言不是意大利语(而是任何其他语言),则必须首先过滤“data”字段中包含关键字“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 {
                    $0.data == "italiano"
                }) { busso in
                    ForEach(dm.JSON.filter {
                        $0.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 {
                    $0.autore == "storia"
                }) { busso in
                    ForEach(dm.JSON.filter {
                        $0.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 { $0.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()
    }
}

【问题讨论】:

  • 在您的 DownloadManager 中,您应该将 JSON 数据转换为本地数据类型,然后在您的视图中过滤数据类型。这将使过滤和避免在您的视图中使用“英语”变得更加容易。能否提供 JSON 数据的链接?
  • 根据需要的逻辑过滤模型,并将结果存储在 UI 中使用的已发布属性中。
  • @nicksarno 是的,这是link...如果有帮助,我在问题中添加了 DownloadManager 的代码...
  • 您应该更新您的问题,以便清楚预期的结果应该是什么。您是否打算如果语言不是意大利语,那么您应该先过滤autore,然后再过滤data?还是应该先过滤data,然后过滤autore 两种语言?
  • @Andrew 是的,感谢您的建议,我会立即更新问题...

标签: json filter swiftui field


【解决方案1】:

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

几个注意事项:

  • 尝试在 DownloadManager 中进行所有过滤和数据管理。我添加了一个过滤器函数,它在数据下载和视图初始化时调用。
  • 尽量避免将字符串硬编码到您的代码中。我创建了一个 Language 枚举来处理“english”和“italian”过滤器。
  • 如果您在代码中遇到过复制整个部分的情况(例如在您的帖子中您重写了“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
}

【讨论】:

  • 感谢您的回答!是的,这就是我想要的结果......不幸的是,应用程序发布的最后期限很紧,我无法进一步尝试你的建议,但我一定会在未来做......同时,我找到了一种可能不会的方法如此优雅,但有效:ForEach(dm.JSON.filter { $0.data == "italiano" && $0.autore == "storia" }) { busso in 这样我通过“数据”字段(语言)和“autore”字段(类别)同时过滤 JSON,而无需编写两个嵌套的 ForEach...所以暂时没关系!再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多