Как передать dictionary в TableView

dictionary
tableview

#1

хочу передать данные из dictionary в TableView. Погуглил, выходит так, что для этого надо вначале создать промежуточный массив.

Вопрос такой - это единственный путь и напрямую передать из dictionary в TableView невозможно?


#2

TableView как бы не принимает никаких данных. Ему все равно где у вас хранятся данные. Вы сами заполняете таблицу своими данными, предварительно подготовив их.


#3

поясните, плз. Возможно я не точно выразился. Есть данные в словаре [String: String]. Нужно передать их в таблицу. Пытаюсь использовать indexPath.row - выдает ошибку, что это невозможно, потому что indexPath есть тип Int.


#4

У вас ключевое значение в словаре String, а indexPath.row это Int.
Если нужно доставать по индексу, тогда попробуйте так

let dictValue = Array(dictionary.values)[indexPath.row]

Если же нужен и ключ и значение

let dictItem = Array(dictionary)[indexPath.row]
let key = dictItem.key
let value = dictItem.value

#5

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


#6

Единственное, порядок в таком случае может быть нарушен.


#7

по идее можно дополнительно использовать метод sorted(). Но с другой стороны, если мы уже создали массив, то там ведь должно быть уже все упорядочено?


#8

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


#9

Работает! Thank you so much!

А подскажите здесь же еще такой вопрос - приведение типов нужно делать только тогда когда есть несколько таблиц (TableViewControllers)?

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FirstTableViewController

И в чем различие здесь между as! и as?


#10

as? будете использовать для определения конкретного типа ячейки, если таблица использует разные.

let cellId = // логика получения идентификатора конкретной ячейки
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)

if let aCell = cell as? FirstViewCell {
    // ...
} else if let aCell = cell as? SecondViewCell {
    // ...
}

return cell

#11

Okay, спасибо. Немного стало понятнее.


#12

Для доступа по индексу в словарях можно использовать subscript:

extension Dictionary {
    subscript(i:Int) -> (key:Key,value:Value) {
        get {
            return self[index(startIndex, offsetBy: i)];
        }
    }
}

Например:
let dict = ["one" : 1, "two" : 2 ]

тогда dict[0].value - это значение ключа “one”, т.е. 1

естественно, словарь - это неупорядоченная коллекция и результаты могут быть разными, но доступ по Int реализован :slight_smile:


#13

Если ключи в словаре будут Int, ваше расширение тут же все ломает.

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


#14

там задача была :slight_smile:

в словаре [String: String]

ну и если индекс будет не в диапазоне тоже всё сломается )))


#15

Но мы то не знаем, используются ли в приложении другие сочетания словарей. Если у него в другом месте где-то было бы обращение по ключу, то после этого расширения, он увидел бы магию и долго ломал голову :slight_smile:
Мне это напоминает эффект бабочки :slight_smile:


#16

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


#17

Тут вы конечно правы. Я начинающий :slight_smile: , и поэтому опытный программист, как вы, сразу видит правильное решение. Мне почему-то сразу сабскрпит вспомнился - вот и всё. Ваше решение явно элегантнее ))


#18

Я правильно понимаю, что способ Array(dictionary)[index] только с swift 4 стал доступен?


#19

Вот этого я не знаю.


#20

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

Вопрос такой - как в данном случае лучше сформировать источник данных?