What I’m trying to do is group the sections in the TableView. By sorting them by the storeName
so that I can separate the items to go to its proper section and arranged by StoreName
.
Im trying to present a couple of different sections of items in the list for each store. By grouping the sections based on StoreName
.
The Items
Array contains all the items for each in each section and shows which store the item belongs to.
How would I be able to group the sections for specific stores?
I know that im close at grouping my sections but im just not sure how to make it work correctly as well as it connecting to my Custom HeaderCell
. I have a function written in my StoreVC
called attemptToAssembleStoreGroups()
I just want to know how would I be able to group my items together by their storeName
to have their own section for each store with its own list of items.
struct ItemSelection {
let store: String
let productName: String
let productImage: UIImage
let quantity: String
let total: String
}
struct ItemSection {
let title : String
let stores : [ItemSelection]
}
class StoreVC: UITableViewController {
fileprivate let cellId = "id123"
let items = [
ItemSelection(store: "Walmart",
productName: "Bionicle",
productImage: #imageLiteral(resourceName: "Bionicle"),
quantity: "4",
total: "24"),
ItemSelection(store: "Walmart",
productName: "PokeBall",
productImage: #imageLiteral(resourceName: "PokeBall"),
quantity: "2",
total: "30"),
ItemSelection(store: "Target",
productName: "Beer",
productImage: #imageLiteral(resourceName: "Beer"),
quantity: "2",
total: "30"),
ItemSelection(store: "Lego Store",
productName: "Star Wars Set",
productImage: #imageLiteral(resourceName: "Star_Wars_Set"),
quantity: "4",
total: "256"),
ItemSelection(store: "Lego Store",
productName: "Indiana Jones Set",
productImage: #imageLiteral(resourceName: "Indiana_Jones_Set"),
quantity: "2",
total: "88"),
ItemSelection(store: "Amazon",
productName: "Coconut Milk",
productImage: #imageLiteral(resourceName: "Coconut_Milk"),
quantity: "4",
total: "20"),
ItemSelection(store: "Amazon",
productName: "32 inch Tv",
productImage: #imageLiteral(resourceName: "TV"),
quantity: "1",
total: "156"),
ItemSelection(store: "Amazon",
productName: "Amazon Echo",
productImage: #imageLiteral(resourceName: "Amazon_Echo"),
quantity: "1",
total: "80"),
ItemSelection(store: "Amazon",
productName: "Grill",
productImage: #imageLiteral(resourceName: "Grill"),
quantity: "3",
total: "90"),
ItemSelection(store: "Amazon",
productName: "Coconut Bar",
productImage: #imageLiteral(resourceName: "coconuts"),
quantity: "4",
total: "240")
]
var itemSelection = [[ItemSelection]]()
var storeArray = [String]()
var itemSections = [ItemSection]()
override func viewDidLoad() {
super.viewDidLoad()
for index in self.items {
storeArray.append(index.store)
}
let groupedDictionary = Dictionary(grouping: items, by: {String($0.store.prefix(1))})
let keys = groupedDictionary.keys.sorted()
itemSections = keys.map{ItemSection(title: $0, stores: groupedDictionary[$0]!.sorted(by: {$0.store < $1.store}))}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return itemSections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemSections[section].stores.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! StoreCell
let itemSelections = itemSelection[indexPath.section][indexPath.row]
cell.itemSelction = itemSelections
return cell
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cartHeader = tableView.dequeueReusableCell(withIdentifier: "Header") as! HeaderCell
let stores = itemSelection[section]
cartHeader.storeName.text = "Store: \(stores)"
return cartHeader
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}
}
class StoreCell: UITableViewCell {
@IBOutlet weak var itemQty: UILabel!
@IBOutlet weak var itemName: UILabel!
@IBOutlet weak var itemPrice: UILabel!
@IBOutlet weak var itemImage: UIImage!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
var itemSelection: ItemSelection! {
didSet {
itemName.text = itemSelection.productName
itemQty.text = "Qty: \(itemSelection.quantity)"
itemPrice.text = "$\(itemSelection.total)"
itemImage.image = itemSelection.productImage
}
}
}
class HeaderCell: UITableViewCell {
@IBOutlet weak var storeName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
found my solution
import Foundation
struct Items {
let store: String
let productName: String
let productImage: UIImage
let quantity: String
let price: String
}
extension Items: Comparable {
static func < (lhs: Items, rhs: Items) -> Bool {
if lhs.store < rhs.store { return true }
else { return lhs.store == rhs.store && lhs.productName < rhs.productName }
}
}
extension Items {
static let retail: [Items] = [
.init(store: "Amazon",
productName: "Care Bear",
productImage: #imageLiteral(resourceName: "Bear"),
quantity: "4",
price: "156"),
.init(....
]
}
import Foundation
class ItemDataSource: NSObject {
var sections: [String: [Items]] = [:]
var items: [String] {
return sections.keys.sorted()
}
var indexes: [String] {
return items
.map { String($0.first!) }
.reduce(into: Set<String>(), { $0.insert($1) })
.sorted()
}
init(stores: [Items]) {
for store in retail.sorted(by: <) {
let items = store.items
if var stores = sections[items] {
stores.append(store)
sections[items] = stores
} else {
sections[items] = [store]
}
}
}
}
class StoreHeader: UITableViewCell {
@IBOutlet weak var dispensaryName: UILabel!
var store: String? {
didSet { storeName.text = "Store: \(store!)" }
}
}
class StoreCell: UITableViewCell {
@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var productQty: UILabel!
@IBOutlet weak var productPrice: UILabel!
@IBOutlet weak var productName: UILabel!
var product: String? {
didSet { productName.text = product }
}
var quantity: String? {
didSet { productQty.text = "Qty: \(quantity!)" }
}
var price: String? {
didSet { productPrice.text = "$\(price!)" }
}
var img: UIImage? {
didSet { productImage.image = img }
}
}
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let dataSource: ItemDataSource = .init(stores: Items.stores)
@IBOutlet weak var tableView: UITableView!
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let store = dataSource.items[section]
return dataSource.sections[store]?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let storeCell = tableView.dequeueReusableCell(withIdentifier: "StoreCell") as! StoreCell
let store = dataSource.items[indexPath.section]
let storeItem = dataSource.sections[store]?[indexPath.row]
storeCell.product = storeItem?.productName
storeCell.price = storeItem?.price
storeCell.quantity = storeItem?.quantity
storeCell.img = storeItem?.productImage
return storeCell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let storeHeader = tableView.dequeueReusableCell(withIdentifier: "StoreHeader") as! StoreHeader
storeHeader.store = dataSource.items[section]
return storeHeader
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}