Swift: How to Display Parsed JSON Data in CollectionView inside a TableView? - arrays

I'm trying to display my data as this image.
My problem is that data displayed inside table view rows are all the same thing, while it should display all data of the array.
This is the code I used to display the collectionView inside the tableView:
var onlineNews = ["local", "Economy", "Variety", "international", "sport"]
var storedOffsets = [Int: CGFloat]()
var tableIndexPath: IndexPath!
#IBOutlet var listTableView: UITableView!
var tableIndex: Int = 0
var categoryResults = [JSON]() {
didSet {
listTableView.reloadData()
}
}
let requestManager = RequestManager()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
for i in onlineNews {
requestManager.categoryList(sectionName: i)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return onlineNews.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! NewsTableViewCell
tableIndex = indexPath.row
return cell
}
func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? NewsTableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: (indexPath as NSIndexPath).row)
tableViewCell.collectionViewOffset = storedOffsets[(indexPath as NSIndexPath).row] ?? 0
}
func tableView(_ tableView: UITableView,
didEndDisplaying cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? NewsTableViewCell else { return }
storedOffsets[(indexPath as NSIndexPath).row] = tableViewCell.collectionViewOffset
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return categoryResults.count
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ColCell",
for: indexPath) as! NewsCollectionViewCell
cell.contentType.text = categoryResults[indexPath.row]["ContentType"].stringValue **// This is where I get the same values for all table view rows**
cell.sectionName.text = onlineNews[tableIndex]
return cell
}
I'm sure someone can absolutely help me with this as I know that it takes only a small tweak to make it work, but not sure where.
Update:
I have followed a way that I believe should work, which is to declare the JSON array to be like this [[JSON]], and then use categoryResults[collection.tag][indexPath.item]["ContentType"].stringValue to get to the value. However, it gives me "index out of range" message. Do you have any clue how can I solve the issue?
var onlineNews = ["local", "Economy", "Variety", "international", "sport"]
var storedOffsets = [Int: CGFloat]()
#IBOutlet var listTableView: UITableView!
var tableIndex: Int = 0
var categoryResults = [[JSON]]() { // updated
didSet {
listTableView.reloadData()
}
}
let requestManager = RequestManager()
override func viewDidLoad() {
super.viewDidLoad()
requestManager.resetCategory()
updateSearchResults()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateSearchResults), name: NSNotification.Name(rawValue: "categoryResultsUpdated"), object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
for i in 0..<onlineNews.count {
requestManager.categoryList(sectionName: onlineNews[i])
}
}
func updateSearchResults() {
categoryResults = [requestManager.categoryResults] // updated
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return onlineNews.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! NewsTableViewCell
tableIndex = indexPath.row
return cell
}
func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? NewsTableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: (indexPath as NSIndexPath).row)
tableViewCell.collectionViewOffset = storedOffsets[(indexPath as NSIndexPath).row] ?? 0
}
func tableView(_ tableView: UITableView,
didEndDisplaying cell: UITableViewCell,
forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? NewsTableViewCell else { return }
storedOffsets[(indexPath as NSIndexPath).row] = tableViewCell.collectionViewOffset
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return categoryResults[collectionView.tag].count // updated
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ColCell",
for: indexPath) as! NewsCollectionViewCell
cell.contentType.text = categoryResults[collectionView.tag][indexPath.row]["ContentType"].stringValue // updated
return cell
}
This the content of RequestManager class (where I call the API):
var categoryResults = [JSON]()
func categoryList(sectionName: String) {
let url = "http://mobile.example.com/api/Content?MobileRequest=GetCategoryNews&PageNo=1&RowsPerPage=10&Category=\(sectionName)&IssueID=0&Type=online"
print("this is the url \(url)")
Alamofire.request(url, method: .get).responseJSON{ response in
if let results = response.result.value as? [String:AnyObject] {
let items = JSON(results["Data"]?["OnlineCategoryNews"]! as Any).arrayValue
self.categoryResults += items
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "categoryResultsUpdated"), object: nil)
}
}
}
func resetCategory() {
categoryResults = []
}
deinit {
NotificationCenter.default.removeObserver(self)
}
Update 2:
And here is the method where the collectionView.tag is assigned. This is added to the tableViewCell class:
func setCollectionViewDataSourceDelegate
<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
(dataSourceDelegate: D, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row
collectionView.bounds.size.width = self.bounds.size.width
collectionView.reloadData()
}

Collection view delegate methods don't know context of their collection view. You should calculate onlineNews index depending on the collectionView instance instead of using indexPath.row, which is internal collection view index path.
Edit: better option (to avoid scrolling and layout issues) is to use single collection view, where cells are grouped in rows. If you don't want to make layout manager, you can achieve such layout by adding small, but very wide separator views between sections
Edit2:
cell.contentType.text = categoryResults[indexPath.row]["ContentType"].stringValue
uses local indexPath of this collection view. You could assign tag to tableViewCell.collectionView with a value of desired categoryResults index. Then you can use this tag as in categoryResults[collectionView.tag]

Related

Following tutorial hacking with swift, coded exact same thing, but in the output console, my output is coming this "[ ]"

when I tried to use this code to get the images, I'm not getting list list of images
import UIKit
class ViewController: UITableViewController {
var pictures = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)
for item in items {
if item.hasPrefix("nssl"){
//load pics
pictures.append(item)
}
}
print(pictures)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pictures.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Picture", for: indexPath)
cell.textLabel?.text = pictures[indexPath.row]
return cell
}
}

Remove item from array in UITableview

What I'm trying to accomplish is when user selects an element for UITableView this element gets append to servicioSeleccionadoarray. But I'm stuck in this because if user decides to deselect the cell I want to remove that item from the array. I've try anyarray.remove(at:)but I can figure the way to tapp into that index.
This is my code so far.
class ServicioHogarViewController: UIViewController{
let serviciosHogar = [String](arrayLiteral: "Alfombras", "Muebles Madera", "Sillones", "Marmol", "Aplicación Teflón","Vestiduras", "Salas", "Colchones", "Sillas Oficinas")
#IBOutlet weak var servicioHogarTB1: UITableView!
var selectedIndex : Int? = nil
var servicioSeleccionado : [String] = []
#IBAction func doneButton(_ sender: UIButton) {
performSegue(withIdentifier: "datePick2", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
servicioHogarTB1.delegate = self
servicioHogarTB1.dataSource = self
servicioHogarTB1.register(UINib(nibName: "ServicioHogarCell", bundle: nil), forCellReuseIdentifier: "servicioCell1")
servicioHogarTB1.separatorStyle = .none
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
print(servicioSeleccionado)
}
}
// MARK : UITabeView Delegation
extension ServicioHogarViewController : UITableViewDelegate, UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return serviciosHogar.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == .checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = .none
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
if tableView.cellForRow(at: indexPath)?.accessoryType == .checkmark {
servicioSeleccionado.append(serviciosHogar[indexPath.row])
print(servicioSeleccionado)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "servicioCell1", for: indexPath) as! ServicioHogarCell
let servicio = serviciosHogar[indexPath.row]
cell.servicioLabel.text = servicio
return cell
}
}
If you have an array :
var cast = ["Vivien", "Marlon", "Kim", "Karl"]
and you want to remove "Marlon" from it, you can find the index of Marlon using the func firstIndex(of: Element) -> Int? method for an array and then remove it like so :
if let index = cast.firstIndex(of: "Marlon"){
cast.remove(at: index)
print(cast)
}
That said, on didSelectRowAt run this function for your array and you'll accomplish what you're looking to.

How to get Label text of UITableView Cell using Swift?

I want to make simple UITabelView. I registered it's cell with my custom class which named as backgroundviewcell. I want to get Label of the selected cell. I tried many times but the output is coming nil value. I have also tried solution from stack overflow but it does not work for me. This is my cellForRowAt indexPath code :
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> backgroundViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "soundElementalcell") as! backgroundViewCell
let imageNames = sections[indexPath.section].images[indexPath.row]
cell.Labeltittle.text = sections[indexPath.section].items[indexPath.row]
cell.Labeltittle.textColor = UIColor(hex : 0x90BA27)
cell.LabelDetail.text = sections[indexPath.section].detail[indexPath.row]
//cell.detailTextLabel?.textColor = UIColor.red
//cell.isHighlighted = false
cell.backgroundColor = UIColor.clear
cell.iconview.image = UIImage(named: imageNames)
return cell
}
This is my didSelectRowAt indexPath code :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)!
celltext = currentCell.textLabel!.text
performSegue(withIdentifier: "showPlayer", sender: self)
}
and my Segue Method is :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPlayer" {
let playerVC = segue.destination as! PlayerViewController
playerVC.trackName = (celltext)! as String
}
}
This is working for me:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! YourCellType
let labelContent = cell.labelToAccess.text
}
First line creates an instance of your cell type (or standard cell, not my case).
The second saves the content of your label (labelToAccess in this case) in a constant.
Instead of accessing the text from the cell's label you need to access the array that you have used to fill the tableView's cell data.
So you need to use UITableViewDelegate method didSelectRowAtindexPath and access the array that you are using with your tableView methods.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.row)
//Access the array that you have used to fill the tableViewCell
print(yourArray[indexPath.row])
}
Note: Once confirm that TableView delegate is properly connected with your ViewController so that it will call didSelectRowAt method when you select cell.
Edit: If you want to pass the data then try like this way.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showPlayer", sender: indexPath) //Pass indexPath as sender instead of self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPlayer" {
let playerVC = segue.destination as! PlayerViewController
let indexPath = sender as! IndexPath
playerVC.trackName = sections[indexPath.section].items[indexPath.row]
}
}
Try this 'Swift 4' -
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCellTxt = yourTableView.cellForRow(at: indexPath)! as? YourCustomTableViewCell
print(currentCellTxt?.lblYourName?.text) // 'lblYourName' that you defined in your 'YourCustomTableViewCell'
}
You didn't set any text for textLabel. Hence it returns nil value.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> backgroundViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "soundElementalcell") as! backgroundViewCell
let imageNames = sections[indexPath.section].images[indexPath.row]
cell.Labeltittle.text = sections[indexPath.section].items[indexPath.row]
cell.Labeltittle.textColor = UIColor(hex : 0x90BA27)
cell.LabelDetail.text = sections[indexPath.section].detail[indexPath.row]
//cell.detailTextLabel?.textColor = UIColor.red
//cell.isHighlighted = false
cell.backgroundColor = UIColor.clear
cell.iconview.image = UIImage(named: imageNames)
return cell
}
In didSelectRow func try to get value from Labeltittle.text not from textLabel.text
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)!
celltext = currentCell.Labeltittle.text
performSegue(withIdentifier: "showPlayer", sender: self)
}

Cannot subscript a value of type [String] with an index of type [NSIndexPath] - prepareForSegue

I'm trying to send multiple rows from a UITableView to another UITableView using prepareForSegue function.
When I just send one option to the 2nd UITableView, the app works perfectly, BUT when I'm choose multiple rows and send those to the second UITableView as a header (for example, if I click first in "a" row, then "d" row and then "c" row... the second UITableView just show me the row "c" as a header, not the other 2 rows), it gives an error.
Pic of the error:
These are the lines I wrote for the first UITableView:
let array = ["a", "b", "c", "d", "e"]
#IBOutlet var initialTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initialTableView.allowsMultipleSelection = true
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueA" {
if let destination = segue.destinationViewController as? Content {
if let selectedRows = initialTableView.indexPathsForSelectedRows {
destination.title = array[selectedRows]
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellA", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = array[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell?.accessoryType == UITableViewCellAccessoryType.Checkmark) {
cell!.accessoryType = UITableViewCellAccessoryType.None
} else {
cell!.accessoryType = UITableViewCellAccessoryType.Checkmark
}
}
The second view contains these lines:
var contentArray:[String] = []
#IBOutlet var contentTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
contentArray.append(title!)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return contentArray.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellContent = tableView.dequeueReusableCellWithIdentifier("cellContent", forIndexPath: indexPath) as UITableViewCell
cellContent.textLabel!.text = "Second test"
return cellContent
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return contentArray[section]
}
So, if I wanna choose multiples rows and send these from the first to the second UITableView... how can I solve this error?
Thanks.
Your problem is that selectedRows is an array of NSIndexPaths. You can't use that to index into your array. You need to pass an array of Strings to your second view controller instead of just setting a single string.
Use map to select the strings from array to pass to the contentArray property of the destination viewController:
destination.contentArray = selectedRows.map { array[$0.row] }
You'll need to decide a new sensible setting for destination.title.
You'll want to remove this line from viewDidLoad:
contentArray.append(title!)

How do I populate two sections in a tableview with two different arrays using swift?

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 section should have a heading "Some Data 1" and the second section should be titled "KickAss".
I have both sections populating with data from the first array (but with no headings either).
Here is my code so far:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rowCount = 0
if section == 0 {
rowCount = Data1.count
}
if section == 1 {
rowCount = Data2.count
}
return rowCount
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let ip = indexPath
cell.textLabel?.text = Data1[ip.row] as String
return cell
}
in the cellForRowAtIndexPath method, is it possible for me to identify the section somehow like I did in the numberOfRowsInSection method?
Also, how do I give titles to each section?
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
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
}
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!
In Swift 4 or Swift 5 you can use the code below.
Here a custom header section with filter is shown:
create a project
Add table view
create UITableView Cell
Connect label to uitable view & table with view controller
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
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.
}
}

Resources