0

以下のような Dictionary データ構造があり、TableViewController でそれらをグループ化して、グループ A がtitle = Aで始まるMyDataを表示し、同時に、Title から取得した利用可能な文字でsectionIndexTitlesForTableViewを表示しようとしています。

【これが私のやりたいこと】

プロトタイプ

辞書のタイトル要素からすべての最初の文字を削除して、以下のコードを使用してセットに保存しようとしましたが、アプリを実行すると、結果がテーブルに複製されます。

私は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。指定されたキーに対して 1 つの値を返すもの
とは異なり、配列内のすべてのメンバーのキーの値を返します。objectForKeyvalueForKeyalphabet

このコードは、文字の を作成しSetて重複を削除し、文字を に戻して並べArray替えます。

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 に答える