在swift中搜索JSON

时间:2017-09-12 15:37:04

标签: json swift uisearchbar

我正在尝试在此JSON中找到匹配的关键字。例如,我希望在标题,数字或用户数组中包含sam的对象。

[
    {
        "title":"List of students",
        "number": "12 stu",
        "users":[{
            "id": 12,
            "name":"tom"
        },
        {
            "id": 1,
            "name":"sam"
        }]
    },
    {
        "title":"List of tutors",
        "number": "2 tut",
        "users":[{
            "id": 1,
            "name":"John"
        },
        {
            "id": 1,
            "name":"Sam"
        }]
    }
]

使用我的代码,我只能搜索标题和数字,但无法搜索每个用户。

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    arrResf = arrRes.filter({ (item) -> Bool in         
        let heading: NSString = ((item["title"]! as? String)! + (item["number"]! as! String)) as NSString
        return (heading.range(of: searchText, options: NSString.CompareOptions.caseInsensitive).location) != NSNotFound
    })
    self.tableView.reloadData()
}

如何扩展搜索以包含用户。

感谢。

3 个答案:

答案 0 :(得分:1)

您的代码存在许多问题。不要在Swift中使用NSString。不要强行解开选择权。

我会按如下方式实现您的过滤器:

arrResf = arrRes.filter { (item) -> Bool in
    // Check the title
    if let title = item["title"] as? String, title.range(of: searchText, options: .caseInsensitive) != nil {
        return true
    }

    // Check the number
    if let number = item["number"] as? String, number.range(of: searchText, options: .caseInsensitive) != nil {
        return true
    }

    // Check the users name
    if let users = item["users"] as? [[String:Any]] {
        for user in users {
            if let name = user["name"] as? String, name.range(of: searchText, options: .caseInsensitive) != nil {
                return true
            }
        }
    }

    return false
}

此代码假设您要返回标题,编号或任何用户所在的任何项目。名称与搜索文本匹配。

答案 1 :(得分:0)

result = array.filter { item in
  let title = item["title"] as? String ?? ""
  let number = item["number"] as? String ?? ""
  let users = (item["users"] as? [[String: Any]]) ?? []
  let usersString = users.reduce("") { result, dictionary in
    [result, dictionary["name"]].flatMap { $0 }.joined(separator: "\t")
  }
  let finalString = [title, number, usersString].joined(separator: "\t")
  return finalString.lowercased().contains(searchTerm.lowercased())
}

由于用户是一个字典数组,我会使用reduce,这可以帮助您将数组“减少”为单个值。我在这里做的是遍历数组中的所有字典,并将name的值添加到字符串中。

一些细节:

  • 应尽可能避免将Swift对象转换为NS个对象。它将使您的代码更清洁。
  • 应避免强制解包选项,如果您的字典在代码中没有“title”值,则会崩溃。最好使用默认值运算符??
  • 虽然您可以将其与字典一起使用,但我建议您创建一个可以从您的JSON字典初始化的struct

答案 2 :(得分:0)

从中制造可腐烂物体:

struct Item: Decodable {
   let title: String
   let number: String
   let users:[User]
}

struct User: Decodable {
 let id: Int
 let name: String
}

之后,您可以使用Array的所有功能来搜索您的物品!