1

我一直在尝试用复选标记在 UITableView 上做 SearchBar。用户一次只能勾选一个。我设法做复选标记和搜索。但是当我在搜索结果上进行搜索并选中标记时,这就是它开始失败的地方

import UIKit

class CandyTableViewController : UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {

    var lastSelectedIndexPath = NSIndexPath(forRow: 0, inSection: 0)

    var candies = [Candy]()
    var mySelected=String()


    var filteredCandies = [Candy]()

    override func viewDidLoad() {
        self.candies = [Candy(category:"Chocolate", name:"chocolate Bar"),
            Candy(category:"Chocolate", name:"chocolate Chip"),
            Candy(category:"Chocolate", name:"dark chocolate"),
            Candy(category:"Hard", name:"lollipop"),
            Candy(category:"Hard", name:"candy cane"),
            Candy(category:"Hard", name:"jaw breaker"),
            Candy(category:"Other", name:"caramel"),
            Candy(category:"Other", name:"sour chew"),
            Candy(category:"Other", name:"gummi bear")]

        mySelected=candies[lastSelectedIndexPath.row].name

    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView == self.searchDisplayController!.searchResultsTableView {
            return self.filteredCandies.count
        } else {
            return self.candies.count
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell

        cell.accessoryType = .Checkmark


        var candy : Candy
        if tableView == self.searchDisplayController!.searchResultsTableView {
            candy = filteredCandies[indexPath.row]

        } else {
            candy = candies[indexPath.row]

        }

        if mySelected==candy.name {
            cell.accessoryType = .Checkmark
            lastSelectedIndexPath=indexPath
        } else {
            cell.accessoryType = .None
        }

        cell.textLabel.text = candy.name

        return cell
    }

    func filterContentForSearchText(searchText: String, scope: String = "All") {
        self.filteredCandies = self.candies.filter({( candy : Candy) -> Bool in
            var categoryMatch = (scope == "All") || (candy.category == scope)
            var stringMatch = candy.name.rangeOfString(searchText)
            return categoryMatch && (stringMatch != nil)
            })
    }

    func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
        let scopes = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
        let selectedScope = scopes[self.searchDisplayController!.searchBar.selectedScopeButtonIndex] as String
        self.filterContentForSearchText(searchString, scope: selectedScope)
        return true
    }

    func searchDisplayController(controller: UISearchDisplayController!,
        shouldReloadTableForSearchScope searchOption: Int) -> Bool {
            let scope = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
            self.filterContentForSearchText(self.searchDisplayController!.searchBar.text, scope: scope[searchOption])
            return true
    }

    func searchDisplayController(controller: UISearchDisplayController, willHideSearchResultsTableView tableView: UITableView) {
        self.tableView.reloadData()
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        tableView.deselectRowAtIndexPath(indexPath, animated: true)

       if indexPath.row != lastSelectedIndexPath?.row {
            if let lastSelectedIndexPath = lastSelectedIndexPath {
                let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
                oldCell?.accessoryType = .None
            }
            let newCell = tableView.cellForRowAtIndexPath(indexPath)
            newCell?.accessoryType = .Checkmark
            lastSelectedIndexPath = indexPath
            mySelected = newCell?.textLabel.text ?? ""


      }

        if candies[indexPath.row].name != candies[lastSelectedIndexPath.row].name {

                let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
                oldCell?.accessoryType = .None
            }

            let newCell = tableView.cellForRowAtIndexPath(indexPath)
            newCell?.accessoryType = .Checkmark

            lastSelectedIndexPath = indexPath

            mySelected = newCell?.textLabel.text ?? ""


    }

  }

我希望它能够在搜索后进行复选标记。并在返回完整列表时保持这种状态。请帮忙,我已经尝试解决这个问题几天了。

更新:我设法按预期做。但相信代码可以比这更简单

4

2 回答 2

2

您需要修复一个错误,然后进行一些更改以使搜索结果中的选择显示在常规表格视图中。

首先,错误 - in tableView:didSelectRowAtIndexPath:,您的设置myselected如下:

myselected=candies[indexPath.row].name

这在常规表视图中工作正常,但在搜索结果中,indexPath.row并没有指向candies数组的正确成员。由于您通过糖果的名称来跟踪,只需将名称从选定的行中取出:

myselected = newCell?.textLabel?.text ?? ""

如果您使用此更改运行代码,您不会看到任何差异,因为您没有在搜索后重新加载主表视图。为此,请实现委托方法searchDisplayController:willHideSearchResultsTableView:

func searchDisplayController(controller: UISearchDisplayController, willHideSearchResultsTableView tableView: UITableView) {
    self.tableView.reloadData()
}

差不多好了!为表格视图配置单元格时,您正在为当前单元格添加复选标记,但不会从其他单元格中清除它。将您的代码稍微更改为:

if myselected==candy.name {
    cell.accessoryType = .Checkmark
    lastSelectedIndexPath=indexPath
} else {
    cell.accessoryType = .None
}
于 2014-11-24T20:41:20.037 回答
0

解决方案有点棘手。@Nate Cook 解决了其中一个问题:

mySelected = newCell?.textLabel.text ?? ""

第二个问题是在搜索模式和正常模式下正确取消选择。您需要了解 NSIndexPath 是您的情况的动态值。例如:

正常模式下的表(索引 = indexPath.row)

+-------+------+
| Index | Name |
+-------+------+
|     0 | A    |
|     1 | B    |
|     2 | C    |
|     3 | BB   |
+-------+------+

例如,我们选择了第 4 行,所以现在我们有了lastSelectedIndexPath = 3. 如果您选择新行,您的代码将使用 lastSelectedIndexPath 正确取消选择行。

但是……让我们看看当您使用关键字B激活搜索时发生了什么。

+-------+------+
| Index | Name |
+-------+------+
|     0 | B    |
|     1 | BB   |
+-------+------+

查看索引,它们发生了变化!现在,当您尝试选择名称为B的行时,您的脚本会尝试取消选择带有lastIndexPath = 3. 但是没有这样的索引行,因为你有绝对新的索引。

那么我们能做些什么呢?每次 UITableView 使用 Checkmark 制作单元格时,我们都可以重新生成 lastIndexPath。您已经这样做了,这是正确的解决方案,我只是更详细地描述了正在发生的事情(您已经更改了没有描述的代码)。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        // cutted some code
        cell.accessoryType = .Checkmark
        lastSelectedIndexPath=indexPath
}

如果您只有一个复选标记,则该代码是最简单的解决方案。如果您需要存储多个复选标记,则需要编写更复杂的代码。这个问题只是关于使用 searchController 存储 1 个复选标记。

于 2016-01-12T22:05:52.950 回答