0

我有一个如下所示的 Dictionary 数据结构,我试图将它们分组到我的 TableViewController 中,以便 A 组显示以title = A开头的MyData ,同时显示sectionIndexTitlesForTableView以及从 Title 获得的可用字母。

【这是我想要达到的】

原型

我试图从我的字典中的标题元素中删除所有第一个字母,并使用下面的代码将它们保存在一个集合中,但是当我运行我的应用程序时,我得到的结果在我的表中重复。

我对 swift 很陌生,很高兴得到有关如何实现这一目标的指导。

这是我的字典数据:

var data: [[String:AnyObject]] =

[
  [
    "id": "1",
    "title": "A Title",
    "alphabet": "A",
    "Detail": "This is a String"
  ],      
  [
    "id": "2",
    "title": "A Title Again",
    "alphabet": "A",
    "Detail": "This is a String"
  ],
  [
    "id": "3",
    "title": "B Title",
    "alphabet": "B",
    "Detail": "This is a String"
  ],
  [
    "id": "4",
    "title": "B Title Again",
    "alphabet": "B",
    "Detail": "This is a String"
  ]
]

这是我的尝试:

class Index: UITableViewController {

var MyData = data

var letters = Set<String>()


override func viewDidLoad() {
    super.viewDidLoad()
    for element in MyData {
        var title = element["title"] as? String
        let letter = title?.substringToIndex(advance(title!.startIndex, 1))         
        letters.insert(letter!)
    }


  MyData =   MyData.sort { element1, element2 in
        let title1 = element1["title"] as? String
        let title2 = element2["title"] as? String

        return title1 < title2
    }

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return letters.count
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.MyData.count
}


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

        cell!.textLabel?.text = (MyData[indexPath.row]["title"] as! String)

    return cell!

}
4

1 回答 1

0

问题是numberOfRowsInSection必须返回每个部分的行数,在您的示例中,第 0 部分为 2,第 1 部分为 2

valueForKey您可以使用经常被误认为的键值编码方法来收集您的字母集objectForKey
objectForKey返回给定键的一个值不同,它返回数组中所有成员valueForKey的键的值。alphabet

此代码创建一个Set字母以清除重复项,将其转回为 anArray并对其进行排序。

let letters = (data as NSArray).valueForKey("alphabet") as! [String]
let filteredLetters = Set<String>(letters)
let sortedLetters = Array(filteredLetters).sorted {$0 < $1}

如果保证所有的值alphabet——以及其他键——String就没有必要将它们转换为可选项。

然后在numberOfRowsInSection你必须过滤每个部分的项目数

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   return data.filter { ($0["alphabet"] as! String) == sortedLetters[section] }.count
}

请注意,表达式不需要强制转换,sortedLetters[section]因为编译器知道这是一个String.

当然,您还必须cellForRowAtIndexPath为非常昂贵的部分检索适当的项目,因为主数组将被多次过滤。
我建议转换dataviewDidLoad()一个以字母为键的新字典和一个包含以这个特定字母开头的项目作为值的数组。这是关于速度和性能的最佳解决方案。

这是一个完整的解决方案(不显示用于快速搜索的字母)

class TableViewController: UITableViewController {

  let data: [[String:String]] =

  [
    [
      "id": "1",
      "title": "A Title",
      "alphabet": "A",
      "Detail": "This is a String"
    ],
    [
      "id": "2",
      "title": "A Title Again",
      "alphabet": "A",
      "Detail": "This is a String"
    ],
    [
      "id": "3",
      "title": "B Title",
      "alphabet": "B",
      "Detail": "This is a String"
    ],
    [
      "id": "4",
      "title": "B Title Again",
      "alphabet": "B",
      "Detail": "This is a String"
    ]
  ]


  var letters = [String]()
  var dataSource = [String:AnyObject]()

  override func viewDidLoad() {
    super.viewDidLoad()

    for value in data  {
      let letter = value["alphabet"]!
      if dataSource[letter] == nil {
        letters.append(letter)
        dataSource[letter] = [[String:AnyObject]]()
      }
      var array = dataSource[letter] as! [[String:AnyObject]]
      array.append(value)
      dataSource.updateValue(array, forKey: letter)
    }
    letters.sorted {$0 < $1}
    tableView.reloadData()

  }

  // MARK: - Table view data source

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return letters.count
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let letter = letters[section]
    return dataSource[letter]!.count
  }


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

    let letter = letters[indexPath.section]
    let letterArray = dataSource[letter]! as! [[String:AnyObject]]
    let item = letterArray [indexPath.row]
    if let title = item["title"] as? String {
      cell.textLabel?.text = title
    }
    return cell
  }

  override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return letters[section]
  }
}
于 2015-08-23T12:34:44.153 回答