Данные группы в представлении сбора заголовков - PullRequest
0 голосов

Как я могу сгруппировать мои данные, полученные из firebase в представление сбора заголовков ?

С база данных Я получил массив с этими данными:

{
    "N7AooUYQU576hb5qLux" : {
        "requested_date" : 20190110,
        "requested_times" : {
            0: 1,
            1: 2,
    }
    "0ckbfkwm2yR0wbcEQ2XT" : {
        "requested_date" : 20190110,
        "requested_times" : {
            0: 3,
            1: 4,
    }
    "38kBVw01kvJtYTtYt0ba" : {
        "requested_date" : 20190211,
        "requested_times" : {
            0: 5,
            1: 6,
    }
    "3bQ3WTwasALxqNNR9P4c" : {
        "requested_date" : 20190315,
        "requested_times" : {
            0: 1,
            1: 2,
    }
    "51OhvSiBGDa0HH8WV5bt" : {
        "requested_date" : 20190211,
        "requested_times" : {
            0: 10,
            1: 11,
    }
}

Для извлечения данных из магазина Я использую этот код:

var bookingHall: [BookingHall] = []
var document: [DocumentSnapshot] = []

fileprivate func observeQuery() {
    guard let query = query else { return }
    listener = query.addSnapshotListener { [unowned self] (snapshot, error) in
        if let err = error {
            self.unknownError(error: err)
        } else {
            if let snapshot = snapshot {
                let bookingModel = snapshot.documents.map { (document) -> BookingHall in
                    if let newBooking = BookingHall(dictionary: document.data()) {
                        return newBooking
                    } else {
                        fatalError("Fatal error")
                    }
                }
                self.bookingHall = bookingModel
                self.document = snapshot.documents
                self.collectionView.reloadData()
            }
        }
    }
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return ...
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.bookingHall.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "studioBookCollCell", for: indexPath) as! StudioBookCollectionCell
    let timeStart = self.bookingHall[indexPath.item].requestedTimes.first!
    let timeEnd = self.bookingHall[indexPath.item].requestedTimes.last! + 1
    cell.timeLabel.text = String(format: "%02d:00 - %02d:00", timeStart, timeEnd)
    return cell
}

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerBook", for: indexPath) as! StudioBookCollectionReusableView
    header.dateLabel.text = ""
    return header
}

Конечный результат, который я хотел бы видеть, похож на картинку ниже:

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

Скажите, пожалуйста, как это можно сделать? Если понадобится больше кода, я обновлю свой пост.

My struct :

protocol BookingDocumentSerializable {
    init?(dictionary:[String:Any])
}

struct BookingHall {

    var contactInfo: [String: Any] = [:]
    var creationDate: Timestamp
    var requestedTimes: [Int] = []
    var uid: String = ""
    var hall: String = ""
    var requestedDate: Int = 0

    var dictionary: [String: Any] {

        return [

            "contact_info": contactInfo,
            "creation_date": creationDate,
            "requested_times": requestedTimes,
            "uid": uid,
            "hall": hall,
            "requested_date": requestedDate

        ]
    }
}

extension BookingHall: BookingDocumentSerializable {

    init?(dictionary: [String: Any]) {

        let contactInfo = dictionary["contact_info"] as? [String: Any] ?? [:]
        let creationDate = dictionary["creation_date"] as? Timestamp
        let requestedTimes = dictionary["requested_times"] as? [Int] ?? []
        let uid = dictionary["uid"] as? String ?? ""
        let hall = dictionary["hall"] as? String ?? ""
        let requestedDate = dictionary["requested_date"] as? Int ?? 0

        self.init(contactInfo: contactInfo,
                  creationDate: creationDate!,
                  requestedTimes: requestedTimes,
                  uid: uid,
                  hall: hall,
                  requestedDate: requestedDate)    
    }
}

enter image description here

Ответы [ 4 ]

2 голосов
/ 05 мая 2019

Вы можете использовать grouping для достижения ваших требований.

INIT (группировка: по:)

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

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

let aryData = [BookingHall]() // Your main array

//Create dicationary with grouped value with `requested_date`
let dict = Dictionary(grouping: aryData, by: { $0.requested_date })

//Format Array for populate data into UITableView
let allKeys = Array(dict.keys)



let aryFinalData = [FinalData]()
for value in allKeys{
    let data = FinalData(title: value, aryData: dict[value]!)
    aryFinalData.append(data)
}


func numberOfSections(in collectionView: UICollectionView) -> Int {
    return aryFinalData.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return aryFinalData[section].aryData.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cellData = aryFinalData[indexPath.section].aryData[indexPath.item]
    return cell
}


func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerBook", for: indexPath) as! StudioBookCollectionReusableView
    let headerData = aryFinalData[indexPath.section]
    header.dateLabel.text = headerData.requested_date
    return header
}

Создать новую структуру для заголовка и суб-массива

struct FinalData{
    let title:String?
    let aryData:[BookingHall]?
}
1 голос
/ 05 мая 2019

Создать словарь для хранения сгруппированных данных

var bookingHall: [BookingHall] = []
var groupedHalls: [Int: [BookingHall]] = [:]

После присвоения значений массиву self.bookingHall сгруппировать данные по дате

self.bookingHall = bookingModel
groupedHalls = Dictionary(grouping: bookingHall, by: { $0.requestedDate })
collectionView.reloadData()

Использовать этот словарь в источнике данных viewview.методы

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return groupedHalls.keys.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return groupedHalls[Array(groupedHalls.keys)[section]]?.count ?? 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let bookingHalls = groupedHalls[Array(groupedHalls.keys)[indexPath.section]]
    let bookingHall = bookingHalls[indexPath.row]
    let timeStart = bookingHall.requestedTimes.first!
    let timeEnd = bookingHall.requestedTimes.last! + 1
    cell.timeLabel.text = String(format: "%02d:00 - %02d:00", timeStart, timeEnd)
    print(bookingHall)
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerBook", for: indexPath) as! StudioBookCollectionReusableView
    header.dateLabel.text = "\(Array(groupedHalls.keys)[indexPath.section])"
    return header
}
0 голосов
/ 05 мая 2019

Вам нужно отобразить ваш JSON как [ (Int, [(Int,Int)] ) ]: ваш массив будет выглядеть так:

[
    ( 20190110, [(1,2), (3,4)] ),
    ( 20190315, [(1,2)]), 
    ( 20190211, [(5,6), (10-11)] )
]

Тогда в numberOfSection вы просто вернете arrayForCollectionView.count

Для самого заголовка:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerBook", for: indexPath) as! StudioBookCollectionReusableView

    header.dateLabel.text = arrayForCollectionView[indexPath.section].0

    return header
}
0 голосов
/ 05 мая 2019

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

Пусть это будет UITableView, и каждый UITableViewCell будет иметь UICollectionView внутри.В этом случае вы можете поместить все свои данные в ячейки collectionView, а заголовки будут принадлежать tableView

Answer's description

Что такоепольза в этом случае?Весь ваш взгляд vertical-scrollable, но каждая ячейка может быть независимо horizontal-scrollable

...