Ios 使用UITexfield进行搜索

Ios 使用UITexfield进行搜索,ios,swift,uitextfield,Ios,Swift,Uitextfield,我想问一下。如何从一个对象中搜索我映射的字符串数组,而不是从uitextfield中搜索它,我尝试了这个方法,但没有成功。我哪里做错了?这是我的代码设置 var cities = [City]() var cityNames = [String]() private func populateCities() { BasicInfoServices.shared.getCity { [weak self] result in switch res

我想问一下。如何从一个对象中搜索我映射的字符串数组,而不是从uitextfield中搜索它,我尝试了这个方法,但没有成功。我哪里做错了?这是我的代码设置

var cities = [City]()
var cityNames = [String]()

    private func populateCities() {
        BasicInfoServices.shared.getCity { [weak self] result in
            switch result {
            case .success(let cities):
                self?.cities = cities
                let names = cities.compactMap { $0.name }
                self?.cityNames = names
            case .failure(let error):
                print(error)
            }
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cityNames.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CitiesAlertCell.cellId, for: indexPath) as! CitiesAlertCell
        cell.selectionStyle = .none
        let item = cityNames[indexPath.row]
        cell.item = item
        return cell
    }

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        searchTextField.resignFirstResponder()
        cityNames.removeAll()
        return true
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if searchTextField.text?.count != nil {
            self.cityNames.removeAll()
            for str in cityNames {
                let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
                if range != nil {
                    cityNames.append(str)
                }
            }
        }
        tableView.reloadData()
        return true
    }

textFieldShouldReturn
方法中,您正在删除所有名称,然后进行迭代。因此将不会有结果。您必须使用另一个数组来保存搜索结果

var filteredCityNames = [String]()

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        filteredCityNames = []
        if searchTextField.text?.count != nil {
            for str in cityNames {
                let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
                if range != nil {
                    filteredCityNames.append(str)
                }
            }
        }
        tableView.reloadData()
        return true
    }

您可以在您的
文本字段shouldReturn
方法中使用此
filteredCityNames
来处理该问题。您正在删除所有名称,然后进行迭代。因此将不会有任何结果。您必须使用另一个数组来保存搜索结果

var filteredCityNames = [String]()

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        filteredCityNames = []
        if searchTextField.text?.count != nil {
            for str in cityNames {
                let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
                if range != nil {
                    filteredCityNames.append(str)
                }
            }
        }
        tableView.reloadData()
        return true
    }

您可以使用这个
filteredCityNames
来实现这一点

因此,除去杂波,您基本上就是这样做的

self.cityNames.removeAll()
for str in cityNames {
    //...
    cityNames.append(str)
}
您从数组中删除所有元素,并尝试对其进行迭代,但由于现在数组中没有任何元素,因此没有任何元素可进行迭代

您可以使用“过滤”数组,它从“主”数组中获取输入。“过滤”数组将显示给用户

var filteredCities: [String]()

private func populateCities() {
    BasicInfoServices.shared.getCity { [weak self] result in
        switch result {
        case .success(let cities):
            self?.cities = cities
            let names = cities.compactMap { $0.name }
            self?.cityNames = names
            self?.filteredCities = names
        case .failure(let error):
            print(error)
        }
    }
}
然后,当您需要筛选列表时

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if searchTextField.text?.count != nil {
        self.filteredCities.removeAll()
        for str in cityNames {
            let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
            if range != nil {
                filteredCities.append(str)
            }
        }
    }
    tableView.reloadData()
    return true
}
这当然意味着您需要在表数据源中使用
filteredCities
而不是
cityNames

说了这么多。我会考虑做点不同的事情。不使用主/过滤器列表,只需使用
cities
数组作为主列表并直接对其进行过滤

if let text = searchTextField.text, !text.isEmpty else { 
    cityNames = cities.filter { $0.name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }.map { $0.name }
} else {
    cityNames = cities.map { $0.name }
}
如果速度是一个问题,您可以返回到
字符串的主/筛选列表
值,这将允许您消除对
映射
结果的需要,但在这一点上,我想问一下,您为什么需要
字符串
列表

例如
如果您担心城市名称为
nil
,那么我会
过滤原始列表,以便主列表只包含有效值

因此,除去混乱,您基本上就是这样做的

self.cityNames.removeAll()
for str in cityNames {
    //...
    cityNames.append(str)
}
您从数组中删除所有元素,并尝试对其进行迭代,但由于现在数组中没有任何元素,因此没有任何元素可进行迭代

您可以使用“过滤”数组,它从“主”数组中获取输入。“过滤”数组将显示给用户

var filteredCities: [String]()

private func populateCities() {
    BasicInfoServices.shared.getCity { [weak self] result in
        switch result {
        case .success(let cities):
            self?.cities = cities
            let names = cities.compactMap { $0.name }
            self?.cityNames = names
            self?.filteredCities = names
        case .failure(let error):
            print(error)
        }
    }
}
然后,当您需要筛选列表时

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if searchTextField.text?.count != nil {
        self.filteredCities.removeAll()
        for str in cityNames {
            let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
            if range != nil {
                filteredCities.append(str)
            }
        }
    }
    tableView.reloadData()
    return true
}
这当然意味着您需要在表数据源中使用
filteredCities
而不是
cityNames

说了这么多。我会考虑做点不同的事情。不使用主/过滤器列表,只需使用
cities
数组作为主列表并直接对其进行过滤

if let text = searchTextField.text, !text.isEmpty else { 
    cityNames = cities.filter { $0.name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }.map { $0.name }
} else {
    cityNames = cities.map { $0.name }
}
如果速度是一个问题,您可以返回到
字符串的主/筛选列表
值,这将允许您消除对
映射
结果的需要,但在这一点上,我想问一下,您为什么需要
字符串
列表

例如
如果您担心城市名为
nil
的话,那么我会
过滤原始列表,这样主列表只包含有效值
cityNames。删除所有的
然后迭代数组是没有意义的。相反,保留一个“主”列表,然后从中生成一个“过滤”列表。您应该为“Filteredata”获取另一个数组,当您搜索时,该数组将加载到TabeView中。否则,您将加载主cityNames数组
cityNames。删除所有
,然后迭代该数组是没有意义的。相反,保留一个“主”列表,然后从中生成一个“过滤”列表。您应该为“filteredData”使用另一个数组,当您搜索时,该数组将加载到TabeView中。否则,您将加载您的主城市名称数组I尝试使用tableView numberOfRow中的filteredCityNames.count,因为当我看到你的代码时,filteredCityNames没有在textfield中使用应该返回。@ManuRaphyYou可以简单地过滤你的模式数组让filteredArray=cities.filter{($0.name.contains(“TextInYourTextField”))}我尝试在tableView numberOfRow中使用filteredCityNames.count,因为当我看到你的代码时,TextField中没有使用的filteredCityNames应该返回。而且它不起作用@manuraphyy你可以简单地过滤你的模式数组让filteredArray=cities.filter{($0.name.contains(“TextInYourTextField”)}