2014-11-20 73 views
0

我一直在尝试使用复选标记在UITableView上做SearchBar。用户一次只能勾选一个标记。我设法做复选标记和搜索。但是,当我搜索和搜索结果对号,这是它开始失败快速UItableview与搜索栏和复选标记

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 ?? "" 


    } 

    } 

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

更新:我设法按照预期完成。但相信这些代码可能会比这更简单

回答

1

您有一个问题需要解决,然后进行一些更改以使搜索结果中的选择显示在常规表视图中。

首先,错误 - 在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 
} 
+1

谢谢你。真的行。感谢你的帮助。只要这行代码xcode需要它就像这样mySelected = newCell?.textLabel.text? “”没有'?'在文本标签上。我仍然对如何使用可选值感到困惑。 – SyamAhmad 2014-11-24 22:08:36

+0

我们可能会在不同的Xcode版本 - 似乎他们仍然来回地说什么属性应该是可选的而不是... – 2014-11-24 22:20:41

+0

我注意到,当我们在搜索后选择与上一行相同的行,复选标记不会发生甚至不同文本。我想我的逻辑'tableView(tableView:UITableView,didSelectRowAtIndexPath indexPath:NSIndexPath)'仍然不正确 – SyamAhmad 2014-11-25 07:03:37

0

解决方法有点棘手。其中一个问题是由固定库克@Nate:

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使用带选中标记的单元格时,我们可以重新生成lastIndexPath。你已经做到了,这是正确的解决方案,我只是更详细地描述了发生了什么(你已经改变了你的代码而没有描述)。

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

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