不搜索第一个字母

Posted

技术标签:

【中文标题】不搜索第一个字母【英文标题】:Not searching the first letter 【发布时间】:2017-04-05 04:04:55 【问题描述】:

我正在将我的 plist 加载到 TableView 中,一切正常,但是现在当我搜索某些内容时,它不会考虑第一个字母。下面你会看到 directory.plist 和我的 Main.storyboard

为了正确加载 plist,我将以下代码放在我的 didFinishLaunchingWithOptions 上:

class AppDelegate: UIResponder, UIApplicationDelegate 

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        if let url = Bundle.main.url(forResource: "directory", withExtension: "plist"), let array = NSArray(contentsOf: url) as? [[String:Any]] 
            Shared.instance.employees = array.mapEmployee(dictionary: $0)
        
        return true

我还有一个结构可以帮助我加载我所有的东西:

struct EmployeeDetails 
    let functionary: String
    let imageFace: String
    let phone: String

    init(dictionary: [String: Any]) 
        self.functionary = (dictionary["Functionary"] as? String) ?? ""
        self.imageFace = (dictionary["ImageFace"] as? String) ?? ""
        self.phone = (dictionary["Phone"] as? String) ?? ""
    

struct Employee 
    let position: String
    let name: String
    let details: [EmployeeDetails] // [String:Any]

    init(dictionary: [String: Any]) 
        self.position = (dictionary["Position"] as? String) ?? ""
        self.name = (dictionary["Name"] as? String) ?? ""
    
        let t = (dictionary["Details"] as? [Any]) ?? []
        self.details = t.map(EmployeeDetails(dictionary: $0 as! [String : Any]))
    


struct Shared 
    static var instance = Shared()
    var employees: [Employee] = []

到这里为止,一切都运行良好!现在我在尝试插入 SearchView 时遇到了麻烦,看看我到目前为止做了什么:

class Page1: UITableViewController, UISearchBarDelegate 
    
    @IBOutlet weak var searchBar: UISearchBar!
    
    var employeesSearching = [Employee]()
    var isSearching : Bool = false

    override func viewDidLoad() 
        super.viewDidLoad()
        
        self.searchBar.delegate = self
    
    
    override func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        if self.isSearching == true 
            return self.employeesSearching.count
         else 
            return Shared.instance.employees.count
        
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
        let employee = Shared.instance.employees[indexPath.row]
        
        if self.isSearching == true 
            cell.nameLabel.text = self.employeesSearching[indexPath.row].name
            cell.positionLabel.text = self.employeesSearching[indexPath.row].position
         else 
            cell.nameLabel.text = employee.name
            cell.positionLabel.text = employee.position
        
        return cell
    
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        if self.searchBar.text!.isEmpty 
            self.isSearching = false
            self.tableView.reloadData()
         else 
            self.isSearching = true
            self.employeesSearching.removeAll(keepingCapacity: false)
            for i in 0..<Shared.instance.employees.count 
                let listItem : Employee = Shared.instance.employees[i]
                if listItem.name.range(of: self.searchBar.text!.lowercased()) != nil 
                    self.employeesSearching.append(listItem)
                
            
            self.tableView.reloadData()
        
    
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if let destination = segue.destination as? Page2,
            let indexPath = tableView.indexPathForSelectedRow 
            destination.newPage = Shared.instance.employees[indexPath.row]
        
    
    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
    

我在搜索的第一个字母时遇到问题。看看:

【问题讨论】:

【参考方案1】:

问题出在这一行:

if listItem.name.range(of: self.searchBar.text!.lowercased()) != nil 

您正在员工姓名的常规文本中查找搜索文本的小写版本。

文本“John Smith”不包含搜索文本“j”。但它确实包含搜索文本“ohn”。

快速解决方法是将该行代码更改为:

if listItem.name.lowercased().range(of: self.searchBar.text!.lowercased()) != nil 

现在比较员工姓名和搜索文本的小写版本。所以现在它会匹配,因为“john smith”包含“j”。

顺便说一句 - 一遍又一遍地小写搜索文本效率低下。还有一种更好的方法来编写循环代码。我会将其更改为:

self.employeesSearching.removeAll(keepingCapacity: false)
let searchText = self.searchBar.text!.lowercased()
for employee in Shared.instance.employees 
    if employee.name.lowercased().range(of: searchText) != nil 
        self.employeesSearching.append(employee)
    

更简单的方法是将代码替换为:

let searchText = self.searchBar.text!.lowercased()
self.employeesSearching = Shared.instance.employees.filter  $0.name.lowercased().range(of: searchText) != nil

要搜索名称或位置的文本,只需更新比较表达式:

if employee.name.lowercased().range(of: searchText) != nil || employee.position.lowercased().range(of: searchText) != nil 

如果您使用filter,请进行类似的更改。

【讨论】:

太棒了!已经完成了,现在只是为了知识。我应该改变什么来不仅搜索name而且搜索position 查看我的更新答案。这是一些非常基本的东西。我恳请您花时间阅读 Apple 的“The Swift Programming Language”一书。您对语言的了解越多,您的生活就会越好。 我正要去做,比你上课好多了!! 我刚刚注意到,当我搜索“Suzan”然后点击Suzan结果时,它显示了“John”的内容。你能看出我的代码有什么问题吗?

以上是关于不搜索第一个字母的主要内容,如果未能解决你的问题,请参考以下文章

在字符串列表中查找字符串中第一个字母的位置(Python 3)

LeetCode 第17题电话号码的字母组合

Javascript从某个位置查找第一个非字母字符的索引

将每个单词的第一个字母大写而不影响连续的字母

将字符串的第一个字母大写,而不触及其他字母

在 UILabel 和 UITextField 中切断第一个而不是最后一个字母?