Словарь в качестве datasource для UITableView

dictionaryfordatasource_proswift_ru_cewrh

Задача

В подавляющем большинстве случаев для заполнения данными не группированной UITableView (т.е. таблицы без секций) мы используем массив — Array. Однако, для заполнения UITableView с секциями, в которой нужно будет указывать наименование секции, а в различных секциях выводить различное количество строк, нужно использовать словарь Dictionary, и при этом произвести некоторые манипуляции, чтобы можно было без проблем получать данные, необходимые от UITableViewDatasource

Пример из жизни: есть словарь, у которого ключи — это месяца года, а значения — это массивы с именами людей, у которых дни рождения в указанном месяце. Хорошо, когда для каждого месяца в словаре имеются данные по людям и это количество людей одинаковое для каждого месяца. Но может же быть, что в январе ни у кого Дня Рождения нет, и тогда, если выводить все секции и строки в таблице «в лоб», можно получить заголовок и отсутствие строк для этого заголовка. Не по фен-шую… И количество строк для каждой секции определяется количеством элементов массива имен.

Также, думаю читатель понимает, что для работы с таблицами нужно оперировать такими понятиями как indexPath. А значения номера строки и секции изменяется от 0 до 11 (это секция — для месяца) и от 0 до N (это количество имен в массиве). Если дни рождения есть только в марте, мае и августе (это третий, пятый и восьмой месяц), то количество секций буде всего лишь три и индекс у них будет от 0 до 2 включительно. Думаю понятно что индекс 2 не совпадает с порядковым номером месяца 8. И вот тут встает вопрос — как извлекать данные из словаря, если из индексация не совпадает с индексацией строк и секций.

Решение

Для решения подобной задачи мы преобразуем словарь с данными в массив и уже будем работать с этим массивом.

Входные данные:

//
// proSwift.ru
//

var bDays = [
"Март": ["Андрей", "Сергей", "Юлия"], 
"Июнь": ["Дмитрий", "Роман"], 
"Август": ["Мария", "Павел"]]

Создадим структуру для хранения данных словаря, и добавим массив этих структур. Этот массив и будет нашим источником данных для таблицы.

//
// proSwift.ru
//

struct Objects {  //Вспомогательная структура
    var sectionName : String!
    var sectionObjects : [String]!
}

var objectArray = [Objects]() // Источник данных

Нужно преобразовать данные из словаря в массив источника данных. Сделать это можно, например во viewDidLoad()

//
// proSwift.ru
//

override func viewDidLoad() {
    super.viewDidLoad()

    for (key, value) in bDays {
        objectArray.append(Objects(sectionName: key, sectionObjects: value))
    }
}

Что же мы сделали?

Для каждой пары ключ-значение их словаря bDays мы создали объект вспомогательной структуры (Object), и присвоили его свойствам sectionName и sectionObjects соответственно ключ словаря и значения по этому ключу. А затем этот объект мы добавили в массив объектов для источника данных.

Теперь количество объектов в массиве соответствует количеству секций таблицы, в свойстве sectionName хранится заголовок для заголовка секции, а в свойстве sectionObjects — массив с именами для таблицы. Количество элементов в массиве имен — количество срок для конкретной секции.

Давайте это все напишем языком Swift 3 для UITableView

//
// proSwift.ru
//


    // MARK: - Table view data source

    
    // Получим количество секций в таблице
    override func numberOfSections(in tableView: UITableView) -> Int {
        return objectArray.count
    }
    
    
    // Получим количество строк для конкретной секции
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objectArray[section].sectionObjects.count
    }
    
    
    // Получим заголовок для секции
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return objectArray[section].sectionName
    }
    
    
    // Получим данные для использования в ячейке
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...
        cell.textLabel?.text = objectArray[indexPath.section].sectionObjects[indexPath.row]
        return cell
    }

Пример

А теперь сделаем небольшой проект, который бы реализовал весь вышеуказанный механизм.

Не буду описывать сам процесс создания проекта, только отмечу, что для отображения секций в таблице нужно указать стиль этой самой таблицы как Grouped

dictionaryfordatasource_proswift_ru_2dj2w

После компиляции и запуска проект будет выглядеть так:

dictionaryfordatasource_proswift_ru_3di3a

Ссылка проекта на GitHub




3 Comments on “Словарь в качестве datasource для UITableView

Добавить комментарий

Ваш адрес email не будет опубликован.

*

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.