0

I Know same question has been asked before , but it did not help.

I am trying to add section titles to my UITableView. I am able to create the sections and count the number of elements in each section properly, , the cells are repeated the data in all the sections.

I am posting only relevant code -

My model is -

 import UIKit
 struct Product:Equatable {
  let imagename: UIImage }

  var productarray = [Product(imagename:#imageLiteral(resourceName: "CakeImage")),
                Product( imagename:#imageLiteral(resourceName: "PeasImge")),Product(imagename:#imageLiteral(resourceName: "vectorlogo")),
                Product(imagename: #imageLiteral(resourceName: "blue"))]

The ProductViewController is -

 import UIKit

 class ProductViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
 let sections = ["Section A", "Section B","Section C", "Section D"]
 let rowspersection = [1, 1,1,1]
 @IBOutlet weak var tableView: UITableView!
 override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate = self
    tableView.dataSource = self   
 }
 func numberOfSections(in tableView: UITableView) -> Int {
   return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return rowspersection[section]
    }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let data = productarray[indexPath.row]
     let cell = tableView.dequeueReusableCell(withIdentifier: "ProductTableViewCell") as! ProductTableViewCell
     cell.imageView?.image =  data.imagename
     cell.myParent = self
       return cell
  }

   func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 44
}
   func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch(section) {
    case 0:return "Section A"
     case 1:return "Section B"
    case  2:return "Section C"
    case  3 :return "Section D"
    default :return ""
        
    }
  }
}

Now, in the above only the first image of the productarray i.e. "[Product(imagename:#imageLiteral(resourceName: "CakeImage"))," is repeated in all the sections as shown in the image below:-

enter image description here

I want all the images/cell to be in the respective sections and not just one image/cell to be repeated in all the sections.

Any help will be appreciated.

askit
  • 205
  • 4
  • 21

2 Answers2

1

in every section indexPath start with zero so it display first index of productarray.

let data = productarray[indexPath.row]

replace with

let data = productarray[indexPath.row + indexPath.section]

Edit

var index = indexPath.row
if indexPath.section != 0, rowspersection.count > indexPath.section - 1{
   index += rowspersection[indexPath.section - 1] 
}
if index < productarray.count{
  let data = productarray[index]
  cell.imageView?.image =  data.imagename
}

Edit Checkout Replace this methods

func updateCart(cell: ProductTableViewCell) {
    guard let indexPath = tableView.indexPath(for: cell) else { return }
    var index = indexPath.row
    if indexPath.section != 0, rowspersection.count > indexPath.section - 1{
        index += rowspersection[indexPath.section - 1]
    }
    
    if index < productarray.count{
        let product = productarray[index]
        
        //Update Cart with product
        cart.updateCart(with: product)
        self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
    }
    
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell   {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ProductTableViewCell") as!   ProductTableViewCell
    cell.delegate = self // original issue was here, now resolved.
    
    var index = indexPath.row
    if indexPath.section != 0, rowspersection.count > indexPath.section - 1{
        index += rowspersection[indexPath.section - 1]
    }
    
    if index < productarray.count{
        let data = productarray[index]
        cell.name?.text = data.name
        cell.imageView?.image =  data.imagename
        
        let product = productarray[index]
        cell.setButton(state: self.cart.contains(product: product))
    }
    
    return cell
}
Dhawal
  • 1,055
  • 6
  • 10
  • -when i follow your code, and I do 2 images each in just 2 sections i.e let sections = ["Section A", "Section B"] & let rowspersection = [2,2] , the second image/cell of the first section(Section A) gets repeated in the first image/cell of the second section(Section B), the original first image/cell of the section(Section B) is nowhere to be found. So, expected images - Section A- CakeImage,PeasImge & Section B - vectorlogo, blue unanticipated images - Section A- CakeImage,PeasImge & Section B - PeasImge, blue How to sort it ? Note - I don’t want to change the model. – askit Sep 16 '20 at 15:51
  • yes, your edited answer is working fine. Upvoted. Thanks. – askit Sep 17 '20 at 04:15
  • okay, there is a stumbling block - when I click on add button for a row of the first section, say "section a" it adds and Checkout(0) becomes 1 i.e. Checkout(1). Till here, its okay, but when I click on add button for a row of another section, say "section b", Checkout(1) again becomes 0 i.e. it becomes Checkout(0). How to straighten it out ?? – askit Sep 22 '20 at 14:03
  • @askit Please share code and your requirement properly so i can understand – Dhawal Sep 22 '20 at 14:07
  • The complete code is here - https://stackoverflow.com/a/64012036/7444874 – askit Sep 22 '20 at 14:38
  • Again a glitch. Supposse there are 4 sections(see image above). Till add button of sections A and B it works fine, but the moment add button of section C is clicked,Checkout again again decreases ! – askit Sep 22 '20 at 23:51
  • moreover , the cells are not properly(initial problem), when there are 4 rows with 2 cells each, the first row cells are fine, but the consequent rows all go haywire ! So, both the issues are not resolved. Please look into it. – askit Sep 23 '20 at 01:18
  • perhaps PGDev's suggestion is right, i.e. changing the model, but the I'll have to change the productviewcontrooller. That will also do. The crux is that I want it to be divided into sections and add to cart to function properly. – askit Sep 23 '20 at 04:02
  • @askit problem is that section A with 4 row and section B with 4 row and this row use same object from productArray when you select same object from any cell it decrease because check this method *func contains(product: Product) -> Bool { let item = items.filter { $0.product == product } return item.first != nil }* – Dhawal Sep 23 '20 at 04:42
  • sill glitchy - Model data in short - a:blue,b:CakeImage,c:vectorlogo, d:PeasImge,e:castle,f:scoobydoo,g:ufo,h:wolfsky,i:universe,j:werewolf,k:galaxy. ProductViewController relevant data - let sections = ["Section A", "Section B","Section C", "Section D","Section E"] let rowspersection = [2,3,2,2,2], and switch accordingly. but the images in Simulator are in order section A:blue,CakeImage. B: vectorlogo, PeasImge, castle. C:PeasImge, castle. D:PeasImge, castle. E:PeasImge, castle. Clicking on Add also acts insanely. – askit Sep 23 '20 at 07:04
  • With all due respect, I am removing it as the selected answer, but not removing the upvote. I hope you do not offended. – askit Sep 24 '20 at 10:25
  • @askit OK np, but why? please tell me the reason. – Dhawal Sep 24 '20 at 13:23
  • because my problem is not sorted out, maybe you have not read yesterday's comment. Its not working fully. I know you have tried a lot, but still not sorted. – askit Sep 24 '20 at 14:09
  • i solved your problem that discribe in your question. and try to solve other issue that not discribe in your question. you need to create other question for other issue. – Dhawal Sep 26 '20 at 16:19
1

Reason:

Since you've a single row in each section, everytime you use indexPath.row which is 0 for the 1st row, you end up accessing productarray[0] for each row in every section.

That's the reason all the rows are same because all of them are filled with productarray[0].

Solution:

Simply use indexPath.section instead of indexPath.row

let data = productarray[indexPath.section]

Note: Instead of making 3 different arrays, you can create a single array of custom type and use that as the dataSource of your tableView. Example:

struct Section {
    let name: String
    let products: [Product]
}

let sections = [
    Section(name: "Section A", products: [Product(imagename:#imageLiteral(resourceName: "CakeImage"))]),
    Section(name: "Section B", products: [Product(imagename:#imageLiteral(resourceName: "PeasImge"))]),
    Section(name: "Section C", products: [Product(imagename:#imageLiteral(resourceName: "vectorlogo"))]),
    Section(name: "Section D", products: [Product(imagename:#imageLiteral(resourceName: "blue"))]),
]

Use sections array as the dataSource. This will avoid a lot of confusion.

PGDev
  • 23,751
  • 6
  • 34
  • 88
  • okay, yes, its workin when I change it to indexpath.section, but I have presented the simplest code to you. How would that go, if say in the above ProductViewController, modify - let sections = ["Section A", "Section B"] & let rowspersection = [2,2] i.e. 2 images each in just 2 ssections Note that I do not want to change the model because the real code is more. Kindly look into my problem. I will be indebted. – askit Sep 16 '20 at 13:53
  • Well, that was just a suggestion based on your current code. Anyways glad that the issue is resolved. Happy coding – PGDev Sep 16 '20 at 13:54
  • Do accept if the answer worked so others won't invest time resolving it. – PGDev Sep 16 '20 at 13:57
  • @Yes, the the question is answered, but the original issue, I am afraid, is not fully resolved. I had presented the simplest code to you. Please read my comment above. – askit Sep 16 '20 at 14:00
  • I did that. And you need to ask a separate question for other problems. A question is considered answered when the problem statement present in the original question is resolved. – PGDev Sep 16 '20 at 14:02