I have two arrays Data1 and Data2 and I want to populate the data within each of these (they contain strings) into a tableview in two different sections.
The first s
You can determine which section you are in by looking at indexPath.section.
To specify the titles, override the function
func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String!
TableView Cells
You could use a multidimensional array. For example:
let data = [["0,0", "0,1", "0,2"], ["1,0", "1,1", "1,2"]]
For the number of sections use:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return data.count
}
Then, to specify the number of rows in each section use:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data[section].count
}
Finally, you need to setup your cells:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellText = data[indexPath.section][indexPath.row]
// Now do whatever you were going to do with the title.
}
TableView Headers
You could again use an array, but with just one dimension this time:
let headerTitles = ["Some Data 1", "KickAss"]
Now to set the titles for the sections:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < headerTitles.count {
return headerTitles[section]
}
return nil
}
The code above checks to see there's a title for that section and returns it, otherwise nil is returned. There won't be a title if the number of titles in headerTitles is smaller than the number of arrays in data.
The Result

Can do Sections in Tableview and can change the colours of Header sections
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tabview: UITableView!
var tablecell = NewTableViewCell()
let data = [["SWIFT", "BALENO", "ALTO", "CIAZ"], ["INNOVA", "GLANZA", "FORTUNER"] , ["BMW X5", "BMW M4", "BMW 7 Series", "BMW X7", "BMW i3"]]
let brand: Array<String> = ["MARUTHI", "TOYOTA", "BMW"]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return brand.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data[section].count }
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.brand[section]
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
// can change the header color of background and title with this code :)
(view as! UITableViewHeaderFooterView).contentView.backgroundColor = UIColor.red.withAlphaComponent(0.4)
(view as! UITableViewHeaderFooterView).textLabel?.textColor = UIColor.yellow
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell1: NewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! NewTableViewCell
let text = data[indexPath.section][indexPath.row]
cell1.textLabel!.text = text
return cell1
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You could create a Struct to hold the data that belongs to a section, as an alternative to my previous answer. For example:
struct SectionData {
let title: String
let data : [String]
var numberOfItems: Int {
return data.count
}
subscript(index: Int) -> String {
return data[index]
}
}
extension SectionData {
// Putting a new init method here means we can
// keep the original, memberwise initaliser.
init(title: String, data: String...) {
self.title = title
self.data = data
}
}
Now in your view controller you could setup your section data like so:
lazy var mySections: [SectionData] = {
let section1 = SectionData(title: "Some Data 1", data: "0, 1", "0, 2", "0, 3")
let section2 = SectionData(title: "KickAss", data: "1, 0", "1, 1", "1, 2")
return [section1, section2]
}()
Section Headers
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return mySections.count
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return mySections[section].title
}
Compared to my previous answer, you now don't have to worry about matching the number of headerTitles to the number of arrays in data.
TableView Cells
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mySections[section].numberOfItems
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellTitle = mySections[indexPath.section][indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = cellTitle
return cell
}
In Swift 4 or Swift 5 you can use the code below.
Here a custom header section with filter is shown:
Add bellow code
import UIKit
struct Category {
let name : String
var items : [[String:Any]]
}
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate {
@IBOutlet weak var txtName: UITextField!
@IBOutlet weak var tableView: UITableView!
var originalArr = [[String:Any]]();
var recentArr = [[String:Any]]();
var searchArrRes = [[String:Any]]()
var searching:Bool = false
//
var sections = [Category]()
override func viewDidLoad() {
super.viewDidLoad()
//Assign delegate don't forget
txtName.delegate = self
tableView.delegate = self
tableView.dataSource = self
recentArr = [
["name": "Enamul", "number": "+8800000003"],
["name": "Enam", "number": "+8800000004"]
]
originalArr = [
["name": "abdul", "number": "+8800000001"],
["name": "abdin", "number": "+8800000002"],
["name": "Enamul", "number": "+8800000003"],
["name": "enam", "number": "+8800000004"],
["name": "Rafi", "number": "+8800000005"],
["name": "Ehaque", "number": "+8800000006"]
]
//my array
sections = [
Category(name:"Recent", items:recentArr),
Category(name:"ALL", items:originalArr)
]
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
guard let tableView = view as? UITableViewHeaderFooterView else { return }
tableView.textLabel?.textColor = UIColor.red
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
//input text
let searchText = textField.text! + string
searchArrRes = self.originalArr.filter({(($0["name"] as! String).localizedCaseInsensitiveContains(searchText))})
if(searchArrRes.count == 0){
searching = false
}else{
searching = true
}
self.tableView.reloadData();
return true
}
func numberOfSections(in tableView: UITableView) -> Int {
if( searching == true){
return 1
}
return self.sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if( searching == true){
return ""
}
return self.sections[section].name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if( searching == true){
return searchArrRes.count
}else{
let items = self.sections[section].items
return items.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Custom_cell
// var dict = itemsA[indexPath.section]
if( searching == true){
var dict = searchArrRes[indexPath.row]
cell.name.text = dict["name"] as? String
cell.number.text = dict["number"] as? String
}else{
let items = self.sections[indexPath.section].items
let item = items[indexPath.row]
cell.name.text = item["name"] as? String
cell.number.text = item["number"] as? String
}
return cell
}
}
You can download full source from GitHub.GitHub Like: https://github.com/enamul95/Custom_table_view_section.git