2015-08-23 2 views
0

У меня есть словарь структуры данных, как показано ниже, и я пытаюсь сгруппировать их в моем TableViewController таким образом, что группа А отображает MyData, который начинается с заголовка = A и в то же дисплей времени разделIndexTitlesForTableView с доступными буквами, полученными от заголовка.группы и сортировки словаря данных в TableViewController с Swift

[Это мой, что я хочу достичь]

Prototype

Я пытался отказаться от всех первых букв из названия элемента в моем словаре, и сохранить их в наборе, используя приведенный ниже код но когда я запускаю свое приложение, я получаю результаты, дублированные в моей таблице.

Я совершенно новый и быстрый, и буду рад, что вы будете руководствоваться тем, как этого добиться.

Вот мой словарь данных:

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! 

} 

ответ

0

Проблема заключается в том numberOfRowsInSection должен возвращать количество строк в разделе, в вашем примере 2 для раздела 0 и 2 для раздела 1

Вы можете получить свой набор букв с помощью метода кодирования значения ключа valueForKey, который часто принимается за objectForKey.
В отличие от objectForKey, который возвращает одно значение для заданного ключа valueForKey, возвращает значение ключа alphabet всех членов массива.

Этот код создает 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, что довольно дорого, потому что основной массив будет фильтроваться несколько раз.
Я бы рекомендовал преобразовать data в viewDidLoad() в новый словарь с буквами в виде ключей и массивом, содержащим элементы, начинающиеся с этой буквы в качестве значений. Это лучшее решение для скорости и производительности.

Здесь полное решение (без отображения букв для быстрого поиска)

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] 
    } 
} 
+0

Большое спасибо за ответ.Я бы хотел, чтобы вы руководствовались в отношении моего кода, чтобы я лучше понял. Я просто полный Начинающий в Свифте. – youngbobby

+1

Ваш код не может работать таким образом, и это слишком сложно, чтобы обеспечить решение на основе вашего кода. Я отправлю полное решение – vadian

Смежные вопросы