Currently Im able to get cells to add up their total in the sections Footer Cell. But it calculates the total for every cell no matter what section its in, inside the all the sections footer.
I still can't get it to add up the different prices(Price1 - 3) for the cells that have a different prices selected passed into it the Section
code im using to add up total in the CartFooter for the Cells in the sections cartFooter.cartTotal.text = "\(String(cart.map{$0.cartItems.price1}.reduce(0.0, +)))"
PREVIOUSLY:
im trying to get the Cells in each section to add up their total in footer cell for each section that they're in.
The data in the CartVC is populated from another a VC(HomeVC). Which is why there is 3 different price options in the CartCell for when the data populates the cells.
Just kind of stuck on how I would be able to get the total in the footer for the cells in the section
Adding specific data for each section in UITableView - Swift
Thanks in advance, Your help is much appreciated
extension CartViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return brands
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let brand = brands[section]
return groupedCartItems[brand]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartCell = tableView.dequeueReusableCell(withIdentifier: "CartCell") as! CartCell
let brand = brands[indexPath.section]
let cartItemsToDisplay = groupedCartItems[brand]![indexPath.row]
cartCell.configure(withCartItems: cartItemsToDisplay.cartItems)
return cartCell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cartHeader = tableView.dequeueReusableCell(withIdentifier: "CartHeader") as! CartHeader
let headerTitle = brands[section]
cartHeader.brandName.text = "Brand: \(headerTitle)"
return cartHeader
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cartFooter = tableView.dequeueReusableCell(withIdentifier: "FooterCell") as! FooterCell
let sectionTotal = cart[section].getSectionTotal()
let calculate = String(cart.map{$0.cartItems.price1}.reduce(0.0, +))
cartFooter.cartTotal.text = "$\(calculate)"
return cartFooter
}
}
Update: these are the results that I am getting using this in the CartFooter
let calculate = String(cart.map{$0.cart.price1}.reduce(0.0, +))
cartFooter.cartTotal.text = "$\(calculate)"
which calculates the overall total (OT) for all the sections and places the OT in all all Footer Cells(as seen below ▼) when im trying to get the total for each section in their footers (as seen in image above ▲ on the right side)
Update2:
this what ive added in my cellForRowAt to get the totals to add up in the section footer. it adds up the data for the cells but it doesn't give an accurate total in the footer
var totalSum: Float = 0
for eachProduct in cartItems{
productPricesArray.append(eachProduct.cartItem.price1)
productPricesArray.append(eachProduct.cartItem.price2)
productPricesArray.append(eachProduct.cartItem.price3)
totalSum = productPricesArray.reduce(0, +)
cartFooter.cartTotal.text = String(totalSum)
}
There's a lot of code, and I'm not too sure where your coding error lies. With that said:
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cartFooter = tableView.dequeueReusableCell(withIdentifier: "FooterCell") as! FooterCell
let sectionTotal = cart[section].getSectionTotal()
let calculate = String(cart.map{$0.cart.price1}.reduce(0.0, +))
cartFooter.cartTotal.text = "$\(calculate)"
return cartFooter
}
Your code seems to say let sectionTotal = cart[section].getSectionTotal() is the total you are looking for (i.e. the total within a section), while you are displaying the OT in a section, by summing up String(cart.map{$0.cart.price1}.reduce(0.0, +)).
In other words, if cartFooter is the container that will display the total within a section, one should read cartFooter.cartTotal.text = "$\(sectionTotal)" instead, no?
If that's not the answer, I suggest that you set a breakpoint each time the footerView is instantiated, and figure out why it output what it outputs (i.e. the OT, instead of the section total).
#Evelyn Try calculation directly in footer. Try below code.
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cartFooter = tableView.dequeueReusableCell(withIdentifier: "FooterCell") as! FooterCell
let brand = brands[indexPath.section]
let arrAllItems = groupedCartItems[brand]!
var total: Float = 0
for item in arrAllItems {
if item.selectedOption == 1 {
total = total + Float(item.price1)
} else item cartItems.selectedOption == 2 {
total = total + Float(item.price2)
} else if item.selectedOption == 3 {
total = total + Float(item.price3)
}
}
cartFooter.cartTotal.text = "$\(total)"
return cartFooter
}
If you want to correct calculate total price in each section you need filter items for every section. now i think you sum all of your section.
For correct section you need yous snipper from your cellForRow method:
let brand = brands[indexPath.section]
let cartItemsToDisplay = groupedCartItems[brand]![indexPath.row]
cartCell.configure(withCartItems: cartItemsToDisplay.cart)
inside this:
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cartFooter = tableView.dequeueReusableCell(withIdentifier: "FooterCell") as! FooterCell
let sectionTotal = cart[section].getSectionTotal()
let brand = brands[section]
let catrItemsToDisplay = // now you need to get associated items with this brand (cart)
// I think it is can looks like this = cartItemsToDisplay[brand]
let calculate = String(cartItemsToDisplay.cart.reduce(0.0, +))
cartFooter.cartTotal.text = "$\(calculate)"
return cartFooter
}
Modify your Model structure and the way values set to through TableViewDelegate. Giving a short hint. Please see if it helps:
class Cart {
var brandWiseProducts: [BrandWiseProductDetails]!
init() {
brandWiseProducts = [BrandWiseProductDetails]()
}
initWIthProducts(productList : [BrandWiseProductDetails]) {
self.brandWiseProducts = productList
}
}
class BrandWiseProductDetails {
var brandName: String!
var selectedItems: [Items]
var totalAmount: Double or anything
}
class SelectedItem {
var image
var name
var price
}
Sections:
Cart.brandWiseProducts.count
SectionTitle:
Cart.brandWiseProducts[indexPath.section].brandName
Rows in section
Cart.brandWiseProduct[indexPath.section].selectedItem[IndexPath.row]
Footer:
Cart.brandWiseProduct.totalAmount
Related
I have a Custom UITableViewCell with a UICollectionView in it.
I have the UICollectionView pinned to each side in its XIB file.
Within some of my cells, the content may carry down but with my current setup for dynamic heights, I am only seeing the top portion. I am adding images to my UICollectionView so in one cell there may be 20 while another may just be 5. Right now each row has the same height when some should be different.
To note, the UICollectionView in the cell will not scroll.
Here is what I am trying in my View Controller:
// Here is where I am getting the arr data, which is the folders
// that contains images.
func getDataForSections() {
let storageReference = Storage.storage()
let ref = storageReference.reference().child("abc/xyz/")
ref.listAll { (result, error) in
if let error = error {
// ...
}
for prefix in result.prefixes {
self.arr.append(prefix)
}
self.myTableView.reloadData()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = arr[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "collectionCell", for: indexPath) as! collectionCell
cell.getImagesFromData(data: data)
cell.frame = tableView.bounds
cell.layoutIfNeeded()
cell.collectionView.reloadData()
cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height).isActive = true
cell.layoutIfNeeded()
return cell
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
// How Do I get the Custom size here? Or in heightForRowAt?
return 500.0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
/**
#param numberOfCellsInCollectionView the number of cells of your current collectioview
*/
func calculateHeight(numberOfCellsInCollectionView: Int) -> CGFloat {
let imageHeight: CGFloat = 40.0
let spaceBetweenRows: CGFloat = 20.0 /*Change as you please based on the space you put between your cells (if any) */
let rows: CGFloat = CGFloat(calculateRows(numberOfCellsInCollectionView: numberOfCellsInCollectionView))
/**
1) (rows*imageHeight) calculate the total space occupied by the pictures
2) (rows+2) assuming you want to put a little space between the top and the bottom of the collectionview i used +2. If you don't want to remove the +2
3) ((rows+2)*spaceBetweenRows) total space occupied by the spaces.
**/
let height = (rows*imageHeight)+((rows+2)*spaceBetweenRows)
return height
}
//Calculate the rows
func calculateRows(numberOfCellsInCollectionView: Int) -> Int {
let result = numberOfCellsInCollectionView/6 //Dividing the number of cells for the cells for row
let rest = numberOfCellsInCollectionView%6 //Calculating the module
if rest == 0 {
//If the rest is 0 (ie: you divide 18/6), then you get the result of the division (18/6 = 3)
return result
} else {
//If the rest is > 0 (ie: you divide 17/6), then you get the result of the division + 1 (17/6 = 3+1 = 4) so there's space for the last item
return result+1
}
}
Here is what I am trying in my Custom Cell that has a Collection View:
func getImagesFromData(prefix: String) {
let storageReference = Storage.storage()
let ref = storageReference.reference().child("abc/xyz/\(prefix)")
ref.listAll { (result, error) in
if let error = error {
// ...
}
self.folderImages.removeAll()
for item in result.items {
if !self.folderImages.contains(item) {
self.folderImages.append(item)
}
}
// Here is where I need to store (or retain) the count
// for each section and then calculate the height or pass
// this data back to the View Controller.
// But with Firebase I am not sure how to return this or
// use a completion.
// reload collection data
self.myCollectionView.reloadData()
}
}
extension customCollectionCell: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return folderImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! imageCell
let theImage = folderImages[indexPath.item]
cell.imageView.sd_setImage(with: theImage, placeholderImage: UIImage(named: "blah")) { (image, error, cacheType, ref) in
if error != nil {
cell.imageView.image = UIImage(named: "blah")
}
}
return cell
}
}
Another Example:
Here instead of using a UITableView with the UICollectionViewCell, I made a UICollectionView with the UICollectionViewCell...
I also use a variation of the method within the cell in the UIViewController to get the count.
In this example, I can see the values prior to the return. I just need to know how to get that value within the return as the height.
Here's what I tried:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let prefix = arr[indexPath.section]
getImageCountFromPrefix(prefix: prefix.name, completion: { (count, success) in
if success {
self.h = self.calculateHeight(numberOfCellsInCollectionView: count)
// self.h has a value!!! How do I get it in the return?
}
})
return CGSize(width: collectionView.bounds.size.width, height: self.h)
}
Create a function to determine the height of the pictures inside the cells then only use the heightForRowAtIndexPath function like this :
private func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
/* Here I'll just assume the height of the picture is 30. You'll have to put here your function and return the dimension. */
return 30.0
}
Note that you may want to add a constant value to the returned value to make the cell's appearance more clear. I usually add 70.0
Oh, and I don't know about images, but when you deal with text you have to call these as well in the cellForRowAt.
cell.textLabel?.sizeToFit()
cell.textLabel?.numberOfLines = 0
Here's how to calculate the height of your collection view
/**
#param numberOfCellsInCollectionView the number of cells of your current collectioview
*/
func calculateHeight(numberOfCellsInCollectionView: Int) -> CGFloat{
let imageHeight: CGFloat = 40.0
let spaceBetweenRows: CGFloat = 5.0 /*Change as you please based on the space you put between your cells (if any) */
let rows: CGFloat = CGFloat(calculateRows(numberOfCellsInCollectionView: numberOfCellsInCollectionView))
/**
1) (rows*imageHeight) calculate the total space occupied by the pictures
2) (rows+2) assuming you want to put a little space between the top and the bottom of the collectionview i used +2. If you don't want to remove the +2
3) ((rows+2)*spaceBetweenRows) total space occupied by the spaces.
**/
let height = (rows*imageHeight)+((rows+2)*spaceBetweenRows)
return height
}
//Calculate the rows
func calculateRows(numberOfCellsInCollectionView: Int) -> Int{
let result = numberOfCellsInCollectionView/6 //Dividing the number of cells for the cells for row
let rest = numberOfCellsInCollectionView%6 //Calculating the module
if rest == 0 {
//If the rest is 0 (ie: you divide 18/6), then you get the result of the division (18/6 = 3)
return result
} else {
//If the rest is > 0 (ie: you divide 17/6), then you get the result of the division + 1 (17/6 = 3+1 = 4) so there's space for the last item
return result+1
}
}
I have a data source in this form:
struct Country {
let name: String
}
The other properties won't come into play in this stage so let's keep it simple.
I have separated ViewController and TableViewDataSource in two separate files. Here is the Data source code:
class CountryDataSource: NSObject, UITableViewDataSource {
var countries = [Country]()
var filteredCountries = [Country]()
var dataChanged: (() -> Void)?
var tableView: UITableView!
let searchController = UISearchController(searchResultsController: nil)
var filterText: String? {
didSet {
filteredCountries = countries.matching(filterText)
self.dataChanged?()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredCountries.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let country: Country
country = filteredCountries[indexPath.row]
cell.textLabel?.text = country.name
return cell
}
}
As you can see there is already a filtering mechanism in place.
Here is the most relevant part of the view controller:
class ViewController: UITableViewController, URLSessionDataDelegate {
let dataSource = CountryDataSource()
override func viewDidLoad() {
super.viewDidLoad()
dataSource.tableView = self.tableView
dataSource.dataChanged = { [weak self] in
self?.tableView.reloadData()
}
tableView.dataSource = dataSource
// Setup the Search Controller
dataSource.searchController.searchResultsUpdater = self
dataSource.searchController.obscuresBackgroundDuringPresentation = false
dataSource.searchController.searchBar.placeholder = "Search countries..."
navigationItem.searchController = dataSource.searchController
definesPresentationContext = true
performSelector(inBackground: #selector(loadCountries), with: nil)
}
The loadCountries is what fetches the JSON and load the table view inside the dataSource.countries and dataSource.filteredCountries array.
Now, how can I get the indexed collation like the Contacts app has without breaking all this?
I tried several tutorials, no one worked because they were needing a class data model or everything inside the view controller.
All solutions tried either crash (worst case) or don't load the correct data or don't recognise it...
Please I need some help here.
Thank you
I recommend you to work with CellViewModels instead of model data.
Steps:
1) Create an array per word with your cell view models sorted alphabetically. If you have data for A, C, F, L, Y and Z you are going to have 6 arrays with cell view models. I'm going to call them as "sectionArray".
2) Create another array and add the sectionArrays sorted alphabetically, the "cellModelsData". So, The cellModelsData is an array of sectionArrays.
3) On numberOfSections return the count of cellModelsData.
4) On numberOfRowsInSection get the sectionArray inside the cellModelsData according to the section number (cellModelsData[section]) and return the count of that sectionArray.
5) On cellForRowAtindexPath get the sectionArray (cellModelsData[indexPath.section]) and then get the "cellModel" (sectionArray[indexPath.row]). Dequeue the cell and set the cell model to the cell.
I think that this approach should resolve your problem.
I made a sample project in BitBucket that could help you: https://bitbucket.org/gastonmontes/reutilizablecellssampleproject
Example:
You have the following words:
Does.
Any.
Visa.
Count.
Refused.
Add.
Country.
1)
SectionArrayA: [Add, Any]
SectionArrayC: [Count, Country]
SectionArrayR: [Refused]
SectionArrayV: [Visa]
2)
cellModelsData = [ [SectionArrayA], [SectionArrayC], [SectionArrayR], [SectionArrayV] ]
3)
func numberOfSections(in tableView: UITableView) -> Int {
return self.cellModelsData.count
}
4)
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionModels = self.cellModelsData[section]
return sectionModels.count
}
5)
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sectionModels = self.cellModelsData[indexPath.section]
let cellModel = sectionModels[indexPath.row]
let cell = self.sampleCellsTableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier",
for: indexPath) as! YourCell
cell.cellSetModel(cellModel)
return cell
}
I have a requirement. Where I have to get the list of students and then I have to show their subjects in which they are enrolled in.
Example
Now you can see below I have list of students i.e Student1, student2, and so on. and each student have different number of subjects
What I have done So far:
I have created a Custom cell that Contains a Label and Empty vertical stackview.
Then in method tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) I am running the for loop that makes some UiLabel dynamically and adds them into the vertical stackview
Problem: By doing this I am getting what I want. But when I scroll up and down the for loop repeats data in the cell again and again on each scroll up/down
Please help if there is anyother way of doing that.
You can use tableview with section.
Set student name in section
Set your subjects in cell
This is sample of tableview with section.
https://blog.apoorvmote.com/uitableview-with-multiple-sections-ios-swift/
Here is the sample code it is just for your reference.
class TableViewController: UITableViewController {
let section = ["pizza", "deep dish pizza", "calzone"]
let items = [["Margarita", "BBQ Chicken", "Pepperoni"], ["sausage", "meat lovers", "veggie lovers"], ["sausage", "chicken pesto", "prawns", "mushrooms"]]
// MARK: - Table view data source
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.section\[section\]
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return self.section.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.items\[section\].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("tableCell", forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = self.items[indexPath.section][indexPath.row]
return cell
}
Update
Customised section view
Create your custom view and show your view as section
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:18))
let label = UILabel(frame: CGRect(x:10, y:5, width:tableView.frame.size.width, height:18))
label.font = UIFont.systemFont(ofSize: 14)
label.text = "This is a test";
view.addSubview(label);
view.backgroundColor = UIColor.gray;
return view
}
Sample code for Customised section
Update 2
Custom header with reference of cell
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCellWithIdentifier("HeaderCell") as! CustomHeaderCell
headerCell.backgroundColor = UIColor.cyanColor()
switch (section) {
case 0:
headerCell.headerLabel.text = "Student Name 1";
//return sectionHeaderView
case 1:
headerCell.headerLabel.text = "Student Name 2";
//return sectionHeaderView
case 2:
headerCell.headerLabel.text = "Student Name 3";
//return sectionHeaderView
default:
headerCell.headerLabel.text = "Other";
}
return headerCell
}
You can try a different approach. Make a list with number of sections = number of students. Each section should have number of rows equal to the subjects for that student. This can be achieved easily by making a student model with subjects array as it's property.
class Student: NSObject {
var subjectsArray : [String] = []
}
First add this extension to your source code.
extension UIStackView{
func removeAllArrangedSubviews() {
let removedSubviews = arrangedSubviews.reduce([]) { (allSubviews, subview) -> [UIView] in
removeArrangedSubview(subview)
return allSubviews + [subview]
}
removedSubviews.forEach({ $0.removeFromSuperview() })
}
}
Now override this method in your Custom cell class. it will remove all child views from stackview before reuse.
override func prepareForReuse() {
super.prepareForReuse()
self.stackView.removeAllArrangedSubviews()
}
I have implemented a tableView using PLIST to set properties.
I would like to add three sections at specific row. (row 12, row24, row 35)
I have tried with following code but it will be too much code and not working well.
Images and code are added below.
import UIKit
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblStoryList: UITableView!
var array = PLIST.shared.mainArray
var array = PLIST.shared.mainArray
let sections: [String] = ["First stage","Second Stage","Third Stage"]
let s1Data : [String] = ["Row1","Row2","Row3"]
let s2Data : [String] = ["Row4","Row5","Row6"]
let s3Data : [String] = ["Row7","Row8","Row9"]
var sectionData: [Int: [String]] = [:]
override func viewDidLoad() {
super.viewDidLoad()
sectionData = [0: s1Data, 1: s2Data, 2: s3Data]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (sectionData[section]?.count)!
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "StoryTableviewCell", for: indexPath) as! StoryTableviewCell
//making plist file
let dict = self.array[indexPath.row]
let title = dict["title"] as! String
let imageName = dict["image"] as! String
let temp = dict["phrases"] as! [String:Any]
let arr = temp["array"] as! [[String:Any]]
let detail = "progress \(arr.count)/\(arr.count)"
//property to plist file
cell.imgIcon.image = UIImage.init(named: imageName)
cell.lblTitle.text = title
cell.lblSubtitle.text = detail
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
The indexPath.row you are getting in the tableView's cellForRowAt is relative to the section. You cannot use it directly as the index of your main array (which has all the rows).
You will need to perform a simple calculation to convert the indexPath.row to an index of that array (by offsetting the row with the total item count of previous sections) :
let index = [0,12,36][indexPath.section] + indexPath.row
let dict = array[index]
The same thing applies to the response you give to numberOfRowsInSection:
return [12,24,35][section]
I find it a bit odd that the data structure (PLIST) would be so rigid that it always contains exactly those number of entries and will never change. I would suggest a more generalized approach if only to avoid spreading hard coded numbers (e.g. 12,24,35,36) all over the place.
for example:
// declare section attributes in your class
let sectionTitles = ["First stage","Second Stage","Third Stage"]
let sectionSizes = [12,24,35] // central definition, easier to maintain (or adjust to the data)
let sectionOffsets = sectionSizes.reduce([0]){$0 + [$0.last!+$1] }
// and use them to respond to the table view delegate ...
let index = sectionOffsets[indexPath.section] + indexPath.row
let dict = array[index]
// ...
return sectionSizes[section] // numberOfRowsInSection
Using this approach, you shouldn't need to create sectionData (unless you're using it for other purposes elsewhere).
BTW, in your sample code, the sectionData content is hard coded with data that is not consistent with the expected section sizes so it would not work even with a correct index calculation.
you can try to use switch case in tableView:cellForRowAtIndexPath:
I want to create a table like this in which on there will be two cells in one section. In first cell the profile image comes and description in the second cell. what I have tried so far is I have set Prototypes to 2 and give each prototype a unique identifier and also created two classes for two prototypes. But The problem is it is showing two rows but both rows have same data.
var profileImage = ["angelina","kevin"]
var userName = ["Angelina Jolie","Vasiliy Pupkin"]
var requestTitle = ["I have a Wordpress website and I am looking for someone to create a landing page with links and a cart to link up.","second description"]
var date = ["Feb 03, 16","Feb 03, 16"]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return profileImage.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return profileImage.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.row==0){
let cell = tableView.dequeueReusableCellWithIdentifier("firstCustomCell", forIndexPath: indexPath) as! FirstProductRequestTableViewCell
cell.userNameLabel.text = userName[indexPath.row]
cell.profileImage.image = UIImage(named: profileImage[indexPath.row])
return cell
}else{
let cell = tableView.dequeueReusableCellWithIdentifier("secondCustomCell", forIndexPath: indexPath) as! SecondProductRequestTableViewCell
cell.requestTitleTxtView.text = requestTitle[indexPath.row]
return cell
}
}
Here is solution for your question.
You need to use UITableViewSecionHeaderView in this case because i think in your scenario you have multiple descriptions against a profile so put the SecionHeader which contain the information of profile and cells contain the description.
But if you want to Repeat the whole cell then you only need to make a CustomCell which contain profile information and description with a line separator. You can make a line separator with an Image or using UIView of height 1.0 and colour lightgray.
Based on your description, the number of sections returned is correct, but you should return 2 for the number of rows in each section and when configuring the cells you should be using indexPath.section where you're currently using the row to choose the data to add to the cell (but keep using the row to choose which type of cell to return).
So, the section is used to choose which person you're showing details about and the row is used to choose which piece of information to show:
var profileImage = ["angelina","kevin"]
var userName = ["Angelina Jolie","Vasiliy Pupkin"]
var requestTitle = ["I have a Wordpress website and I am looking for someone to create a landing page with links and a cart to link up.","second description"]
var date = ["Feb 03, 16","Feb 03, 16"]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return profileImage.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.row == 0) {
let cell = tableView.dequeueReusableCellWithIdentifier("firstCustomCell", forIndexPath: indexPath) as! FirstProductRequestTableViewCell
cell.userNameLabel.text = userName[indexPath.row]
cell.profileImage.image = UIImage(named: profileImage[indexPath.section])
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("secondCustomCell", forIndexPath: indexPath) as! SecondProductRequestTableViewCell
cell.requestTitleTxtView.text = requestTitle[indexPath.section]
return cell
}
}