Unable to select the correct first row in UITableView - ios

I have a table row with 6 rows. I want to have the background colour of the first row to be different but the background color of 4th row ( index 3 ) also changes. I am adding the screenshot of the same and here is the code
import UIKit
var items = ["admksalmdlsamdlsamdlkasmdlasmdlsamdlksamdlkasmdlkasmdlksamdklasmdlkasmdlkasmdlkasmdcjkndscnksndcdkcnksdjcnksdnckjsdncsdnjkanckjanckjsnckjasncjkasnckjasncjkasnckdslnjcvlkjdncjsnjkasncjkasncjkasnckjasncjkasnckjsanckjsanckjasncjksancjksancjksancjkasncjasncjkasncklas;NKCNDJKVALNVJKSDANCKSCNJSNCJKSDCNKJSDNCKJANCDKNLSACNJDKCNJKNCAKJNACJKNKJANCKJSNC","badmksalmdlsamdlsamdlkasmdlasmdlsamdlksamdlkasmdlkasmdlksamdklasmdlkasmdlkasmdlkasmdcjkndscnksndcdkcnksdjcnksdnckjsdncsdnjkanckjanckjsnckjasncjkasnckjasncjkasnckdslnjcvlkjdncjsnjkasncjkasncjkasnckjasncjkasnckjsanckjsanckjasncjksancjksancjksancjkasncjasncjkasncklas;NKCNDJKVALNVJKSDANCKSCNJSNCJKSDCNKJSDNCKJANCDKNLSACNJDKCNJKNCAKJNACJKNKJANCKJSNC", "cadmksalmdlsamdlsamdlkasmdlasmdlsamdlksamdlkasmdlkasmdlksamdklasmdlkasmdlkasmdlkasmdcjkndscnksndcdkcnksdjcnksdnckjsdncsdnjkanckjanckjsnckjasncjkasnckjasncjkasnckdslnjcvlkjdncjsnjkasncjkasncjkasnckjasncjkasnckjsanckjsanckjasncjksancjksancjksancjkasncjasncjkasncklas;NKCNDJKVALNVJKSDANCKSCNJSNCJKSDCNKJSDNCKJANCDKNLSACNJDKCNJKNCAKJNACJKNKJANCKJSNCSDNSAJKDNAKLSMDLAKSDMKLASMDLKASMDLKASMDLKASMDLKASMDLKASMDLKASMDLKASMDLKASMDLKASMLAKSMDLASMDLAKSMDLKASMDLKASMDLKASMLKADSMLKASMDLKASMDLKMadmksalmdlsamdlsamdlkasmdlasmdlsamdlksamdlkasmdlkasmdlksamdklasmdlkasmdlkasmdlkasmdcjkndscnksndcdkcnksdjcnksdnckjsdncsdnjkanckjanckjsnckjasncjkasnckjasncjkasnckdslnjcvlkjdncjsnjkasncjkasncjkasnckjasncjkasnckjsanckjsanckjasncjksancjksancjksancjkasncjasncjkasncklas;NKCNDJKVALNVJKSDANCKSCNJSNCJKSDCNKJSDNCKJANCDKNLSACNJDKCNJKNCAKJNACJKNKJANCKJSNCishan","cool1","hsjndjksndjkasnd","nsjdnknkjandjknasdka"]
class ViewController: UIViewController,UITableViewDelegate {
let basicCellIdentifier = "BasicCell"
#IBOutlet weak var tableView: UITableView!
func configureTableView() {
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160.0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(basicCellIdentifier) as BasicCell
if ( indexPath.row == 0){
cell.userInteractionEnabled = false
cell.backgroundColor = UIColor.grayColor()
}
println(indexPath.row)
cell.titleLabel.text = items[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func viewDidLoad() {
super.viewDidLoad()
println(items.count)
//tableView.reloadData()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

As you are reusing your cells via dequeueReusableCell with identifier as-
let cell = tableView.dequeueReusableCellWithIdentifier(basicCellIdentifier) as BasicCell
according to your requirements you have the background color of the cell for index path 0 to gray color as
if ( indexPath.row == 0)
cell.backgroundColor = UIColor.grayColor()
When this cell is reused for the 4th row(index path.row = 3), than it already has the background color set earlier for row 0 (to gray color), that's why all the reused cell which are reusing the cell of 0th index will be shown with the gray color.
To resolve this issue just add the else case with the above if statement as
if ( indexPath.row == 0)
cell.backgroundColor = UIColor.grayColor()
else
cell.backgroundColor = UIColor.whiteColor()

Related

Swift expanding Tableview cell how to adjust height

hope that somebody can help me, thank you already anyway. So realized an expanding Tableview cell (when i tap the cell it open with more detail) and now i want to adjust the height the cell, how i have to do? because before the cell i want to put an image with a description and i want the cell not on the top but at the end of my controller, i tried to put an imagine in my view controller but i have a error in my code, what code i need for adjust the height and put an image with description before the cell?
class PROVAViewController: UITableViewController {
var tableViewData = [cellData]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableViewData = [cellData(opened: false, title: "Title1", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title1", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title1", sectionData: ["Cell1","Cell2","Cell3"]),
cellData(opened: false, title: "Title1", sectionData: ["Cell1","Cell2","Cell3"])]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
return tableViewData.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableViewData[section].opened == true {
return tableViewData[section].sectionData.count + 1
} else {
return 1
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let dataIndex = indexPath.row - 1
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {return UITableViewCell()}
cell.textLabel?.text = tableViewData[indexPath.section].title
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {return UITableViewCell()}
cell.textLabel?.text = tableViewData[indexPath.section].sectionData[dataIndex]
return cell
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
if tableViewData[indexPath.section].opened == true {
tableViewData[indexPath.section].opened = false
let sections = IndexSet.init(integer: indexPath.section)
tableView.reloadSections(sections, with: .none) // play around with it(cosa significa non lo so, vedi video)
}else{
tableViewData[indexPath.section].opened = true
let sections = IndexSet.init(integer: indexPath.section)
tableView.reloadSections(sections, with: .none)
}
}
}
}
Set the top, bottom, leading, and trailing for the label, also set number of lines to 0.set the tableview height to UITableViewAutomaticDimension. This will make the label and cell grow according to the content.
I am not sure if understood you question Correctly:
Your cell has and imageView with a UILabel next to it with dynamic content.
You can use the following logic.
Step:- 1 Make sure the row size is changed at both the places as shown on Screen shots:
Step:- 2 Drag an imageView and label into cell and get it done with following constraints:
Hope this helps.

Two tableViews in same ViewController won't show in swift 3

I am trying to have two UITableViews in the same ViewController. I am trying to do all of it programmatically but for some reason neither of the tableViews display at all.
I have noticed that the code never gets to
else if tableView == self.tableView2 {
}
in the cellForRowAt method. I have no idea why this is the case.
I appreciate any help to solve this.
import UIKit
class TestViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView1: UITableView?
var tableView2: UITableView?
let tableView1Data = ["Option 1", "Option 2", "Option 3", "Option 4", "Other"]
let tableView2Data = ["Cancel"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .apricot
// Initalize
tableView1 = UITableView()
tableView2 = UITableView()
// Register cells
// tableView1!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell1")
// tableView2!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell2")
tableView1!.register(UINib(nibName: "yourNib", bundle: nil), forCellReuseIdentifier: "Cell1")
tableView2!.register(UINib(nibName: "yourNib", bundle: nil), forCellReuseIdentifier: "Cell2")
// Set delegates
tableView1!.delegate = self
tableView1!.dataSource = self
tableView2!.delegate = self
tableView2!.dataSource = self
// Add to view
view.addSubview(tableView1!)
view.addSubview(tableView2!)
// Set size constraints
tableView1!.translatesAutoresizingMaskIntoConstraints = false
tableView1!.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView1!.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView1!.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView2!.translatesAutoresizingMaskIntoConstraints = false
tableView2!.topAnchor.constraint(equalTo: tableView1!.bottomAnchor, constant: 15).isActive = true
tableView2!.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView2!.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
// Customize looks
tableView1!.layer.cornerRadius = 10
tableView2!.layer.cornerRadius = 10
// Reload data
tableView1!.reloadData()
tableView2!.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
tableView1!.reloadData()
tableView2!.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView1 {
return tableView1Data.count
}
else if tableView == self.tableView2 {
return tableView2Data.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell?
if tableView == self.tableView1 {
cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)
guard let cell = cell else {return UITableViewCell()}
let cellLabel = UILabel()
cellLabel.text = tableView1Data[indexPath.row]
cellLabel.textColor = .black
cell.addSubview(cellLabel)
cellLabel.frame = cell.frame
}
else if tableView == self.tableView2 {
cell = tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath)
guard let cell = cell else {return UITableViewCell()}
let cellLabel = UILabel()
cellLabel.text = tableView2Data[indexPath.row]
cellLabel.textColor = .black
cell.addSubview(cellLabel)
cellLabel.frame = cell.frame
}
return cell!
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return view.frame.height * 0.1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//...
}
}
You need to somehow constrain the height of either tableView1 or tableView2 (Once you have established 1 height, the other can be inferred). At the moment you have told autolayout that the two table views must be 15 apart vertically, but not where that separation is in terms of the superview. As a result, autolayout is probably sizing tableView1 to the full height of the superview and the other tableview isn’t on screen, so it’s datasource methods don’t get called
For example, to set the table views to half the screen each:
TableView1!.bottomAnchor.constraint(equalTo:self.view.centerYAnchor, constant:-7).isActive=true
one caveat with tableView is that it's datasource method will not get called unless view has it's frame . If tableView try to render it self and doesn't find it's frame valid data source method will never get's called.
You need to check if both of the tableView has it's frame defined

UITableViewCell doesn't update height after adding a view to UIStackView

I have a UIStackView inside UITableViewCell's contentView. Based on user interaction, I add/remove items in the UIStackView. After modifying the items in UIStackView, I expect the cell to update it's height accordingly. But, it doesn't update it's height unless I call tableView.reloadData(). But, calling reloadData() in cellForRowAtIndexPath / willDisplayCell becomes recursive.
What is the proper way to adjust the cell height at run time based on items in UIStackView?
I use UITableViewAutomaticDimension
Updating the Problem:
Here is a simple prototype of what I am trying to do.
My actual problem is dequeuing the cell.
In the prototype, I have 2 reusable cells and 3 rows. For row 0 and 2, I dequeue cellA and for row 1, I dequeue cellB. Below is the overview on the condition I use.
if indexPath.row == 0 {
// dequeue cellA with 2 items in stackView
}
if indexPath.row == 1 {
// dequeue cellB with 25 items in stackView
}
if indexPath.row == 2 {
// dequeue cellA with 8 items in stackView
}
But the output is,
row 0 contains 2 items in stackView - expected
row 1 contains 25 items in stackView - expected
row 2 contains 2 items in stackView - unexpected, row 0 is dequeued
I also tried removing all arranged subViews of stackView in cellForRowAtIndexPath. But, doing so, flickers the UI when scrolling. How can I manage to get the desired output?
I believe the problem is when you are adding views to the stack view.
In general, adding elements should take place when the cell is initialized.
willDisplay cell: is where one handles modifying attributes of cell contents.
If you move your code from willDisplay cell: to cellForRowAt indexPath: you should see a big difference.
I just made that one change to the code you linked to, and the rows are now auto-sizing based on the stack view contents.
Edit: Looked at your updated code... the issue was still that you are adding your arrangedSubviews in the wrong place. And you compound it by calling reloadData().
Second Edit: Forgot to handle previously added subviews when the cells are reused.
Updated code... replace your ViewController code with:
//
// ViewController.swift
//
import UIKit
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
tableView.estimatedRowHeight = 56
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if indexPath.row == 0 || indexPath.row == 2 {
cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
if let stackView = cell.viewWithTag(999) as? UIStackView {
let numberOfItemsInStackView = (indexPath.row == 0) ? 2 : 8
let color = (indexPath.row == 0) ? UIColor.gray : UIColor.black
// cells are reused, so clear out any previously added subviews...
// but leave the first view that is part of the cell prototype
while stackView.arrangedSubviews.count > 1 {
stackView.arrangedSubviews[1].removeFromSuperview()
}
// use "i" so we can count
for i in 1...numberOfItemsInStackView {
// use label instead of view so we can number them for testing
let newView = UILabel()
newView.text = "\(i)"
newView.textColor = .yellow
// add a border, so we can see the frames
newView.layer.borderWidth = 1.0
newView.layer.borderColor = UIColor.red.cgColor
newView.backgroundColor = color
let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 54)
heightConstraint.priority = 999
heightConstraint.isActive = true
stackView.addArrangedSubview(newView)
}
}
}
if indexPath.row == 1 {
cell = tableView.dequeueReusableCell(withIdentifier: "lastCell")!
if let stackView = cell.viewWithTag(999) as? UIStackView {
let numberOfItemsInStackView = 25
// cells are reused, so clear out any previously added subviews...
// but leave the first view that is part of the cell prototype
while stackView.arrangedSubviews.count > 1 {
stackView.arrangedSubviews[1].removeFromSuperview()
}
// use "i" so we can count
for i in 1...numberOfItemsInStackView {
// use label instead of view so we can number them for testing
let newView = UILabel()
newView.text = "\(i)"
newView.textColor = .yellow
// add a border, so we can see the frames
newView.layer.borderWidth = 1.0
newView.layer.borderColor = UIColor.red.cgColor
newView.backgroundColor = UIColor.darkGray
let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 32)
heightConstraint.priority = 999
heightConstraint.isActive = true
stackView.addArrangedSubview(newView)
}
}
}
return cell
}
// override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// if cell.reuseIdentifier == "cell" {
// if let stackView = cell.viewWithTag(999) as? UIStackView {
// let numberOfItemsInStackView = (indexPath.row == 0) ? 2 : 8
// let color = (indexPath.row == 0) ? UIColor.gray : UIColor.black
// guard stackView.arrangedSubviews.count == 1 else { return }
// for _ in 1...numberOfItemsInStackView {
// let newView = UIView()
// newView.backgroundColor = color
// let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 54)
// heightConstraint.priority = 999
// heightConstraint.isActive = true
// stackView.addArrangedSubview(newView)
// }
// tableView.reloadData()
// }
// }
//
// if cell.reuseIdentifier == "lastCell" {
// if let stackView = cell.viewWithTag(999) as? UIStackView {
// let numberOfItemsInStackView = 25
// guard stackView.arrangedSubviews.count == 1 else { return }
// for _ in 1...numberOfItemsInStackView {
// let newView = UIView()
// newView.backgroundColor = UIColor.darkGray
// let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 32)
// heightConstraint.priority = 999
// heightConstraint.isActive = true
// stackView.addArrangedSubview(newView)
// }
// tableView.reloadData()
// }
// }
// }
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}
Try to reload only the cell using: https://developer.apple.com/documentation/uikit/uitableview/1614935-reloadrows
Example code
Here is an example. We have basic table view cells (TableViewCell) inside a view controller. The cells have 2 labels inside a stack view. We can hide or show the second label using the collapse/reveal methods.
class TableViewCell : UITableViewCell {
#IBOutlet private var stackView: UIStackView!
#IBOutlet private var firstLabel: UILabel!
#IBOutlet private var secondLabel: UILabel!
func collapse() {
secondLabel.isHidden = true
}
func reveal() {
secondLabel.isHidden = false
}
}
class ViewController : UIViewController {
#IBOutlet var tableView: UITableView!
fileprivate var collapsedCells: Set<IndexPath> = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 128
}
#IBAction private func buttonAction(_ sender: Any) {
collapseCell(at: IndexPath(row: 0, section: 0))
}
private func collapseCell(at indexPath: IndexPath) {
if collapsedCells.contains(indexPath) {
collapsedCells.remove(indexPath)
} else {
collapsedCells.insert(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
if collapsedCells.contains(indexPath) {
cell.collapse()
} else {
cell.reveal()
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
}

Cannot show Table View data in a simple Times Table App

I am trying to make a simple Times Table App (for numbers 1-9) in Swift) using a slider and a Table View. I am managing to make the slider work and an array to be created for each number that is selected with the slider and although the array is shown on the console. I cannot get the numbers to appear on the Table View. Can you please help me and tell me what am I missing?
Here is what I have written so far:
class ViewController: UIViewController, UITableViewDelegate {
#IBOutlet var sliderValue: UISlider!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(sliderValue.value)), animated: true)
print(sliderValue)
var cellContent = [String]()
for var i = 1; i <= 10; i += 1 {
cellContent.append(String(i * Int(sliderValue.value)))
}
print(cellContent)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I'm afraid there's quite a lot in the code you've supplied that doesn't make all that much sense. I've mentioned some of it in my comment above but you've also nested what looks like a tableViewDataSource-function into your sliderMoved function. The whole array thing looks rather flakey as well as the proposed cell-count does not actually consider the size of the array. I think you probably want something like this:
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet var valueSlider: UISlider!
#IBOutlet var tableView: UITableView!
private var cellContent = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(valueSlider.value)), animated: true)
tableView.reloadData()
}
// TableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") // Must exist with the same identifier in your storyboard
cell.textLabel?.text = valueStringForIndex(indexPath.row)
return cell
}
// Private functions
private func valueStringForIndex(index: Int) -> String {
return "\(index * Int(valueSlider.value))"
}
}
Have you tried creating cellContent array as a instance variable and the following code may work. Check it once.
var cellContent = [String]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
#IBAction func sliderMoved(sender: UISlider) {
sender.setValue(Float(lroundf(sliderValue.value)), animated: true)
print(sliderValue)
for var i = 1; i <= 10; i += 1 {
cellContent.append(String(i * Int(sliderValue.value)))
}
print(cellContent)
self.tableview.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Although not directly an answer to your question ->
Depending on how you want the table displayed, a UICollectionView may be a great fit for this application. Very similar to UITableView to implement but with boxes and columns of data, may be simpler to format (and changing the slider could add some fun animation when the collection view updates).
The sample UIViewController below demonstrates using a UICollectionView. In the storyboard, I simply:
Added a UISlider, UICollectionView, and UILabel and created outlets in MultiplicationTableViewController
In the UICollectionView default cell I gave it the reuseIdentifier "numberCell", and added a label (to hold the product)
Made the MultiplicationTableViewController the dataSource and delegate for the UICollectionView
CODE:
import UIKit
class MultiplicationTableViewController: UIViewController {
#IBOutlet var timesTableCollectionView: UICollectionView!
#IBOutlet weak var numberSlider: UISlider!
#IBOutlet weak var label: UILabel!
var products = [Int]() //array to hold the computed value for each cell in the collectionView
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.viewRotated), name: UIDeviceOrientationDidChangeNotification, object: nil) //register for rotation notifications
products = createTableOfValues() //populate products with initial values
label.text = "\(Int(numberSlider.value)) x \(Int(numberSlider.value))"
}
#IBAction func sliderUpdated(sender: UISlider) {
sender.value = Float(Int(sender.value)) //make the slider stop only on whole numbers
label.text = "\(Int(sender.value)) x \(Int(sender.value))"
products = createTableOfValues() //create the new table values
timesTableCollectionView.reloadData() //tell the collectionView to read the new data and refresh itself
}
func createTableOfValues() -> [Int] {
var prod = [Int]() //temp array to hold the generated products
for row in 0...Int(numberSlider.value) { //iterate from row 0 (header) to
var columns = [Int]() //temp array to build column products
for column in 0...Int(numberSlider.value) {//iterate through each column, including column 0 (header)
if column == 0 {
columns.append(row)
} else if row == 0 {
columns.append(column)
} else {
columns.append(column * row)
}
}
prod.appendContentsOf(columns) //add the current row of products to the temp array
}
return prod
}
func viewRotated() {
timesTableCollectionView.reloadData() //called to force collectionView to recalc (basically to get new cell sizes
}
}
extension MultiplicationTableViewController: UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1 //required for UICollectionViewDataSource
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int(numberSlider.value + 1) * Int(numberSlider.value + 1) //tells the UICollectionView how many cells to draw (the number on the slider, plus header rows)
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("numberCell", forIndexPath: indexPath) //get an existing cell if it exists
if cell.frame.origin.y == 0.0 || cell.frame.origin.x == 0.0 { //if the cell is at the top or left of the collectionView
cell.backgroundColor = UIColor.yellowColor()
} else {
cell.backgroundColor = UIColor.clearColor() //If not, reset the color (required because cells are reused
}
cell.layer.borderColor = UIColor.blackColor().CGColor
cell.layer.borderWidth = 1.0
let numberItem = cell.viewWithTag(101) as? UILabel //get a reference to the label in the current cell
numberItem?.text = String(products[indexPath.row]) //get the value generated earlier for this particular cell
return cell
}
}
extension MultiplicationTableViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let columns = CGFloat(numberSlider.value + 1) //get the number of columns - slider value + 1 for header
let width = timesTableCollectionView.bounds.width / columns //divide the width of the collectionView by the number of columns
return CGSizeMake(width, width) //use width value to make the cell a square
}
}
Screenshot:

Two UITableView in single UIViewcontroller not working properly

I want to implement following functionality in app show pict
But i have following problem show another pict
my code as follow
// MARK: UITextFieldDelegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if str == "Loading"{
return 0
}else if tableView == tbl2{
return arrSub.count
}else{
return self.displayData.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:customCellInvitation = self.tableView.dequeueReusableCellWithIdentifier("cell")as! customCellInvitation
if tableView == tbl2{
//Code for the load secind table
cell.lblUserName.text = self.arrSub.objectAtIndex(indexPath.row).valueForKey("username") as?String
cell.btnAdd.setImage(UIImage(named: "yes1.png"), forState:(UIControlState.Normal))
return cell
}else{
//Code for the load first table
cell.lblUserName.text = self.displayData.objectAtIndex(indexPath.row).valueForKey("username") as?String
cell.btnAdd.setImage(UIImage(named: "add.png"), forState:(UIControlState.Normal))
cell.btnAdd.setImage(UIImage(named: "yes1.png"), forState:(UIControlState.Selected))
cell.btnAdd.addTarget(self, action: "addData:", forControlEvents: .TouchUpInside)
cell.btnAdd.tag = indexPath.row
}
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
//function call when user click Plus button
func addData(sender: UIButton!) {
arrSub .addObject(self.displayData .objectAtIndex(sender.tag))
var button:UIButton = sender.viewWithTag(sender.tag) as! UIButton
button.selected=true
button.userInteractionEnabled = false
NSLog("%#", arrSub)
[tbl2 .reloadData()]
}
I would suggest you to move your tableView Datasource and Delegate to separate classes. This is not a good practise at all. You will certainly mess up with your code.
What you are doing make code complexity, you can add you own custom class for tableView and can maintain it it all delegate datasource methods.Add that tableview in current class and with giving frame to it. By this you can add as many number of tableview to a single class and no need to worry about data handling.
Put a frame to this table view, then you can add two frame to a view controller. So add this frame to your view controller, you should adjust the frame width and hight in order to show two tables.
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .None
tableView.frame = CGRectMake(20, (self.view.frame.size.height - 54 * 5) / 2.0, (self.view.frame.size.width - 25 * 5), 54 * 5)
tableView.autoresizingMask = .FlexibleTopMargin | .FlexibleBottomMargin | .FlexibleWidth
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.opaque = false
tableView.backgroundColor = UIColor.clearColor()
tableView.backgroundView = nil
tableView.bounces = false
tableView.showsVerticalScrollIndicator = true
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clearColor()
view.addSubview(tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
// MARK : TableViewDataSource & Delegate Methods
extension LeftMenuViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 54
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
let titles: [String] = ["Home", "Features", "Pricing", "Help", "About Us", "Contact Us"] // put your titles
let images: [String] = ["IconHome", "IconCalendar", "IconProfile", "IconSettings", "IconEmpty", "IconEmpty"] // add images if you want
cell.backgroundColor = UIColor.clearColor() // optional
cell.textLabel?.font = UIFont(name: "HelveticaNeue", size: 21)
cell.textLabel?.textColor = UIColor.whiteColor()
cell.textLabel?.text = titles[indexPath.row]
cell.selectionStyle = .None
cell.imageView?.image = UIImage(named: images[indexPath.row])
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
switch indexPath.row {
case 0:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier("TabBar") as! UIViewController
sideMenuViewController?.contentViewController = viewController
sideMenuViewController?.hideMenuViewController()
break // show table navigation view controller
case 1:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier("TabBar") as! UIViewController
sideMenuViewController?.contentViewController = viewController
sideMenuViewController?.hideMenuViewController()
break // show table navigation view controller
default:
break
}
}
}
// MARK: UITextFieldDelegate Methods
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:customCellInvitation = self.tableView.dequeueReusableCellWithIdentifier("cell")as! customCellInvitation
if tableView == tbl2{
cell.lblUserName.text = self.arrSub.objectAtIndex(indexPath.row).valueForKey("username") as?String
if str = "yes"{
cell.btnAdd.setImage(UIImage(named: "yes1.png"), forState:(UIControlState.Normal))
}else{
cell.btnAdd.setImage(UIImage(named: "NO.png"), forState:(UIControlState.Normal))
}
return cell
}else{
cell.lblUserName.text = self.displayData.objectAtIndex(indexPath.row).valueForKey("username") as?String
if str = "yes"{
cell.btnAdd.setImage(UIImage(named: "yes1.png"), forState:(UIControlState.Normal))
}else{
cell.btnAdd.setImage(UIImage(named: "NO.png"), forState:(UIControlState.Normal))
}
}
return cell
}

Resources