Uitableview with Different Optional Sections

UITableView with different optional sections?

This looks like my way of approaching such problems. I'm using enums (Obj-C & especially Swift) to handle and identify my Sections and I always return the full amount of potential sections:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return FormSection.count // enum function
}

In func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int, however, I switch the unused sections off by returning 0 rows.

The benefit I saw after struggling with your type of dynamic tables was that all sections are always at the same index which made cell management relatively easy:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let section:FormSection = FormSection(rawValue:indexPath.section)!

switch section {
case .Header:
//…
default:
//…
}
}

The same goes for section headers/footers:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
switch section {
case FormSection.Header.rawValue:
return nil
case FormSection.RoomSetup.rawValue where foo == false:
return nil
default:
// return header with title = FormSection(rawValue: section)?.headerTitle()
// Swift enums ftw ;)
}

And the number of rows is calculated/fetched at runtime:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section:FormSection = FormSection(rawValue:section)!
switch section {
case .Section1:
return fooExpanded ? (numberOfFoo) : 0
case .Section2:
return model.barCount()
default:
return 1
}
}

How To use different segues for different UTableView Sections and pass data

First of all you don't need to get the cell in your 'didSelectRowAtIndexPath' method, so the first line where you create a reference to the cell is unnecessary.

You have an index path that has a row and section index within it, use that to obtain the data out of your sectionItems array e.g

let data = sectionItems[indexPath.section][indexPath.row]

switch indexPath.section {
case 0:
self.performSegueWithIdentifier("sectionOneSegue", sender: data)
case 1:
self.performSegueWithIdentifier("sectionTwoSegue", sender: data)
default:
break
}

That should be all you need within that method.

You can then override the prepareForSegue method and check the segue.identifier property to see which segue has been performed and extract the destinationViewController from there. Once you have the view controller you can pass your data to it through a property on the view controller.

if segue.identifier == "sectionOneSegue" {

guard let data = sender as? String,
newViewController = segue.destinationViewController as? NewViewController else {
return
}

newViewController.data = data
}

In the above code I'm making sure that the sender is the expected data type (the one sent from the above performSegueWithIdentifier method) and that the destination controller is the one that I want, then as soon as I know everything is correct I'm setting the property on the destination controller with the data that I want to send to it.

I hope this helps.

CheckBox UITableView with Different Sections

Example using a UIButton with checked / unchecked background images with an on/off state:

//
// TableWithCheckTableViewController.swift
// SWTemp2
//
// Created by Don Mag on 6/6/17.
// Copyright © 2017 DonMag. All rights reserved.
//

import UIKit

class MyCheckTableViewCell: UITableViewCell {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myCheckButton: UIButton!

var checkedImage = UIImage(named: "Checked")
var unCheckedImage = UIImage(named: "UnChecked")

var isOn: Bool = false {
didSet {
myCheckButton.setBackgroundImage(self.isOn ? checkedImage : unCheckedImage, for: .normal)
}
}

var checkTapAction : ((Bool)->Void)?

@IBAction func buttonTapped(_ sender: Any) {

self.isOn = !self.isOn

checkTapAction?(self.isOn)
}

}

// simple data object
class MyCheckObject: NSObject {
var theTitle = ""
var theCheckState = false

init(_ title: String) {
theTitle = title
}
}

class TableWithCheckTableViewController: UITableViewController {

// array of MyObjects
var myData = [MyCheckObject]()

override func viewDidLoad() {
super.viewDidLoad()

// just to make it a little easier to see the rows scroll
tableView.rowHeight = 60

// create 40 data objects for the table
for i in 1...40 {
let d = MyCheckObject("Data Item: \(i)")
myData.append(d)
}

tableView.reloadData()

}

// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCheckTableViewCell", for: indexPath) as! MyCheckTableViewCell

// Configure the cell...
let d = myData[indexPath.row]
cell.myLabel.text = d.theTitle
cell.isOn = d.theCheckState

// set a "Callback Closure" in the cell
cell.checkTapAction = {
(isOn) in
// update our Data Array to the new state of the switch in the cell
self.myData[indexPath.row].theCheckState = isOn
}

return cell
}

}

How to show multiple customcell and a custom section header in one uitableview?

Try to keep as few types of cells as you can. If one type cell is similar to another but with one or two extra labels, just set it all up in the same cell and keep the labels empty on the cell that doesn't need them. That way they can be in the same reuse queue. If the cells are different enough you might need to have more queues. Just instantiate them with a different cellIdentifier and they will get added to the queue for that identifier.

eg.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;

if(indexPath.row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:@"firstRowCell"];

if(!cell) {
cell = [[UITableViewCell alloc] inittWithFrame:CGRectZero reuseIdentifier:@"firstRowCell"];
}

// -- first cell setup

} else {
cell = [tableView dequeueReusableCellWithIdentifier:@"genericRowCell"];

if(!cell) {
cell = [[UITableViewCell alloc] inittWithFrame:CGRectZero reuseIdentifier:@"genericRowCell"];
}

// -- generic cell setup
}

// -- common cell setup

return cell;

}


Related Topics



Leave a reply



Submit