如何使用解析JSON文件中的表观视频添加搜索栏

发布于 2025-01-25 18:38:18 字数 1245 浏览 2 评论 0原文

我已经成功地将带有以下数据模型的JSON文件解析到了我的项目和我的tableview中。

import Foundation

struct ActionResult: Codable {
    let data: [Datum]
}
struct Datum: Codable {
    let goalTitle, goalDescription, goalImage: String
    let action: [Action]
}
struct Action: Codable {
    let actionID: Int
    let actionTit: String
}

现在,我正在尝试创建一个搜索栏来搜索“ ActionTitle”。我的桌面有部分标题和行。

相关代码:

var filteredData: [Action]?
    
    let searchController = UISearchController()
  
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Search"
        searchController.searchBar.delegate = self
        filteredData = ????
        navigationItem.searchController = searchController
        parseJSON()
        
        
                func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            filteredData = []
            if searchText == ""{
                filteredData = ????
            }
            else {
                for actions in ???? {
                if actions.lowercased().contains(searchText.lowercased()) {
                    filteredData.append(actions)
        }

                self.tableView.reloadData()
 }

我不知道要使用什么代码?

谢谢。

I have successfully parsed a JSON file with the following data model into my project and my tableview.

import Foundation

struct ActionResult: Codable {
    let data: [Datum]
}
struct Datum: Codable {
    let goalTitle, goalDescription, goalImage: String
    let action: [Action]
}
struct Action: Codable {
    let actionID: Int
    let actionTit: String
}

Now I am trying to create a searchbar to search on the "actionTitle". My tableview has section headers and rows.

Relevant code:

var filteredData: [Action]?
    
    let searchController = UISearchController()
  
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Search"
        searchController.searchBar.delegate = self
        filteredData = ????
        navigationItem.searchController = searchController
        parseJSON()
        
        
                func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            filteredData = []
            if searchText == ""{
                filteredData = ????
            }
            else {
                for actions in ???? {
                if actions.lowercased().contains(searchText.lowercased()) {
                    filteredData.append(actions)
        }

                self.tableView.reloadData()
 }

I do not know what code to use where I have ????.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一刻暧昧 2025-02-01 18:38:18

您需要保留所有可用数据的实例(Allactions),并始终在tableView中显示过滤器数据(filtereddata)。因此,当没有任何过滤时,filtereddata等于aLLactions,除非您打算在搜索为空时隐藏所有数据)。

searchbar(_:,textdidchange:)调用时,您可以使用 filter(_ :) 评估是否应包括该项目。 Apple的描述在过滤器上关闭:

将序列的元素作为其参数和
返回布尔值,指示该元素是否应为
包含在返回的数组中。

我不知道是否存在声明filtereddata的特定原因:[action]?,是因为在调用parsejson()时才填充数据?如果是这样 - 我建议在数据可用时初始化一个空数组并填充它们。

另外,parsedata()产生datum的实例吗?我相信您的代码不包括在内,因此我添加了datum:datum?
如果我错了,请提供更多信息parsejson()填充,我将更新答案。

var result: ActionResult? {
    didSet {
        guard let result = result else { return }
        allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ($0.0, ($0.1, $0.1.actions)) })
        updateFilteredData()
    }
}


var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()

// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()

let searchController = UISearchController()

override func viewDidLoad() {
    super.viewDidLoad()

    title = "Search"
    searchController.searchBar.delegate = self
    navigationItem.searchController = searchController

    // ...
    parseJSON()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return filteredSectionDataActions.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredSectionDataActions[section]?.actions.count ?? 0
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
    if let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row] {
        // setup cell for action
        cell.textLabel?.text = action.actionTitle
    }
    return cell
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    updateFilteredData(for: searchText.lowercased())
    tableView.reloadData()
}

func updateFilteredData(for searchText: String = String()) {

    if searchText.isEmpty {

        filteredSectionDataActions = allSectionDataActionMap

    } else {

        for (index, (datum, actions)) in allSectionDataActionMap {

            let filteredActions = actions.filter { $0.actionTitle.lowercased().contains(searchText) }

            if filteredActions.isEmpty {

                filteredSectionDataActions[index] = (datum, actions)

            } else {

                filteredSectionDataActions[index] = (datum, filteredActions)

            }
        }

    }

}

You want to keep an instance of all of the available data (allActions), and always show your filter data (filteredData) in the tableView. So when there is nothing to filter, filteredData is equal to allActions (unless you intend to hide all data when the search is empty).

When searchBar(_:,textDidChange:) is called, you can use filter(_:) to evaluate if the item should be included. Apple's description on the filter closure:

A closure that takes an element of the sequence as its argument and
returns a Boolean value indicating whether the element should be
included in the returned array.

I don't know if there is a specific reason for declaring filteredData: [Action]?, is it because the data is not populated until parseJSON() is called? If so--I suggest initializing an empty arrays and populating them when the data is available.

Also, does parseData() produce an instance of Datum? I believe this piece of your code is not included, so I am adding datum: Datum?.
If I am wrong, please provide more info what parseJSON() populates and I will update my answer.

var result: ActionResult? {
    didSet {
        guard let result = result else { return }
        allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ($0.0, ($0.1, $0.1.actions)) })
        updateFilteredData()
    }
}


var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()

// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()

let searchController = UISearchController()

override func viewDidLoad() {
    super.viewDidLoad()

    title = "Search"
    searchController.searchBar.delegate = self
    navigationItem.searchController = searchController

    // ...
    parseJSON()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return filteredSectionDataActions.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredSectionDataActions[section]?.actions.count ?? 0
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
    if let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row] {
        // setup cell for action
        cell.textLabel?.text = action.actionTitle
    }
    return cell
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    updateFilteredData(for: searchText.lowercased())
    tableView.reloadData()
}

func updateFilteredData(for searchText: String = String()) {

    if searchText.isEmpty {

        filteredSectionDataActions = allSectionDataActionMap

    } else {

        for (index, (datum, actions)) in allSectionDataActionMap {

            let filteredActions = actions.filter { $0.actionTitle.lowercased().contains(searchText) }

            if filteredActions.isEmpty {

                filteredSectionDataActions[index] = (datum, actions)

            } else {

                filteredSectionDataActions[index] = (datum, filteredActions)

            }
        }

    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文