I want to add spacing between rows and set the header
here my code is -
#IBOutlet weak var sideMenu: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.logo.setImage(arr[indexPath.row]["icon"] as? UIImage, for: .normal)
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
First Add tableview Delegate and Data Source for both tableview in storyboard by taping control+draging into viewcontroller
Then use the same delegate function to access sidemenu tableview.
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var sideMenu: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableview == sideMenu{
return 2
}else{
//this is for tableView
return 3
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableview == sideMenu{
//use slide menu tableview cell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.grupImage.image = array[indexPath.row]["groupImage"] as? UIImage
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
}else{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.grupImage.image = array[indexPath.row]["groupImage"] as? UIImage
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
}
}
2 ways.
make the view controller data source & delegate for both the tableviews & in the methods add the below check.
if tableview === self.tableview {
//its for table view
return ...
}
// else its for side menu
return ...
Create a separate class (Call it SideMenuTableViewHelper or something) for SideMenu tableView datasource & delegate.
First one is simpler, 2nd one is cleaner for datasource, messier for handling delegate (did select row) methods as they will most likely be triggering code in view controller (which can be done via View controller acting as custom delegate to the SideMenuTableViewHelper). For a beginner, I reckon go with (1).
Related
I take tableView and two different cell.xib files , I want to display when i click cell1 then i should display cell2 data.
class TableView: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var array1 = ["Click1","Click2"]
var array2 = [[ "one","two","Three"],["Four","Five"]]
var selectedArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "MainCell", bundle: nil) , forCellReuseIdentifier: "MainCell")//This is used to add xib file with identifier
tableView.register(UINib(nibName: "SecondCell", bundle: nil) , forCellReuseIdentifier: "SecondCell")
}
//MARK:DataSource Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "MainCell") as! MainCell
cell.textLabel?.text = array1[indexPath.row]
return cell
}
//MARK: tableViewDelegate Method
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "SecondCell") as! SecondCell
selectedArray = array2[indexPath.row]
cell.textLabel?.text = selectedArray[indexPath.row]
}
}
Tell how can i do that if i press first cell it should show 2nd cell values as per indexPath.row
I think you want to achieve expandable cells. You can use the header cell for this one.
You might want to read this:
Hope this helps!
For example, you can add a flag which indicates whether the first cell was tapped.
var wasFirstCellTapped = false
Then numberOfRowsInSection depends on this flag:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return wasFirstCellTapped ? array1.count : 1
}
In didSelectRowAt:indexPath set this flag to true. And perform tableView changes. The simplest way is to call tableView.reloadData(). But you can animate this using insertRowsAtIndexPaths
var allCellsArray = ["Click1","Click2"]
var displayingCellsArray = ["Click1"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return displayingCellsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell!
if displayingCellsArray[indexPath.row] == "Click1" {
cell = self.tableView.dequeueReusableCell(withIdentifier: "MainCell") as! MainCell
}else {
cell = self.tableView.dequeueReusableCell(withIdentifier: "SecondCell") as! SecondCell
}
cell.textLabel?.text = displayingCellsArray[indexPath.row]
return cell
}
//MARK: tableViewDelegate Method
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let data = displayingCellsArray[indexPath.row]
//Below logic will show (Cell2 if Cell1 is clicked and hide Cell1)
// (and show Cell1 if clicked Cell2 and hide Cell2)
if data == "Click1" {
displayingCellsArray = [allCellsArray.last!]
}else {
displayingCellsArray = [allCellsArray.first!]
}
tableView.reloadData()
}
You should handle such logic in a separate datasource array by adding/removing that sort of data from this array which shows particular cells.
E.g
In your case you have two values in array Click1 & Click2
Click1 shows MainCell & Click2 shows SecondCell
So first add Click1 in your array and when this cell is tapped simply add Click2 in your array and reload. If you want to remove MainCell when SecondCell is displaying then while adding Click2 simply remove Click1
You can expand the second cell on click of first cell..
Refer this example to expand and collapse the cells
https://github.com/jonasman/JNExpandableTableView
I'm quite new to Swift and I would like to know what is the easiest and simplest way for me to add in 10 buttons to 10 of my cell rows in my TableViewController.
P.S: It would be nice if the 10 buttons perform differently instead of duplicate.
import UIKit
import FirebaseDatabase
var ref: DatabaseReference?
var databaseHandle: DatabaseHandle?
var postData = [String]()
class TableViewController5: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference() //set the firebase reference
// Retrieve the post and listen for changes
databaseHandle = ref?.child("Posts3").observe(.value, with: { (snapshot) in
postData.removeAll()
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
postData.append(key)
}
self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.font = UIFont.init(name: "Helvetica", size: 23)
cell.textLabel?.text = postData[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 80
}
}
From what I can understand, you should use prototype cell and add an IBAction in the cell and in that cell you should perform the segue and pass whatever data you need to customise the page you load.
In your tableView(_:cellForRowAt:) method, you can set a tag for the button.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? prototypeCell
cell.voteButton.tag = indexPath.row
return cell
}
Then in your cell's class, in the IBAction I mentioned earlier, check for the tag and set the data to pass accordingly.
Then in your prepareForSegue:sender: method, just pass the data you want to pass to the next view controller and all should work fine.
Check if it helps You
//Common cell Variable
var cell = UITableViewCell()
//UIButton commonly Declared
var acceptRequest = UIButton()
var declineRequest = UIButton()
My TableView Cell contains two button as shown Accept & Decline
In my tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) I added Handlers for button
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Cell for dequeuing
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Used Tags here
//You can Make use of TableViewCell class here and Access Buttons from there
acceptRequest = cell.viewWithTag(4) as! UIButton
//Adding action Handlers for UIbuttons
self.acceptRequest.addTarget(self, action: #selector(RequestListView.AcceptRequest(sender:)), for: .touchUpInside)
return cell
}
my Button handler
func AcceptRequest (sender: UIButton) {
//Dequeue cell with identifier can be ignored
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Get button position from TableView : Required
let buttonPosition : CGPoint = sender.convert(CGPoint.zero, to: self.RequestListTableView)
//Get index Path of selected Cell from TableView
//Returns Table Cell index same as didSelect
let indexPath : IndexPath = self.RequestListTableView.indexPathForRow(at: buttonPosition)!
//Can be used if you need to update a view
cell = self.RequestListTableView.cellForRow(at: indexPath)!
//Now time to access using index Path
cell.textLabel.text = array[indexPath.row] //Example
}
Can use this Procedure for even single Button or for multiple buttons too
In case if you have more than one button in one cell, this will help you
Here my code :
#IBOutlet weak var billSelectorBtn: UIButton!
#IBOutlet weak var optionListTB: UITableView!
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return optionsListNames.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as UITableViewCell
cell.textLabel?.text = optionsListNames[indexPath.row] as? String
return cell
}
private func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
let selectedItem = optionsListNames.object(at: indexPath.row) as! NSString
billSelectorBtn.setTitle(selectedItem as String, for: UIControlState.normal)
if selectedItem .isEqual(to: "Current Bill")
{
self.view.backgroundColor = UIColor.red
}
else if selectedItem .isEqual(to: "Water Bill")
{
self.view.backgroundColor = UIColor.green
}
optionListTB.isHidden = true
}
So in my didselectrow method i am check whether the selected string is equal.And if its equal i will keep the ui as some color chnage. But its not working ??
i saw this tutorial : http://www.aegisiscblog.com/how-to-implement-custom-dropdown-list-in-swift.html
please help me out..
Thanks
tableview default color is white that you added in storyboard. To match tableview color to its background view you have to clear the tableview color and vice versa for the Uitableviewcell.
In your viewdidload add this line,
tableview.backgroundColor = UIColor.clear //tableview is your tableview outlet
And in cellForRowAt indexPath
Add,
cell.backgroundColor = UIColor.clear
In swift 3 didselect syntax has been changed to
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
Instead of isEqual, use "==" to compare strings. And make your tableView's backgroundColor and cell's backgroundColor to clear to see the color change, if you have your tableView occupy fullscreen.
Remove private from your delegate method
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
/// add implementation
}
See also
I have
["06:58"]
["07:13", "07:38", "07:53"]
["08:13", "08:38", "08:53"]
["09:13", "09:33", "09:53"]
and I want to show it in tableView as in picture:
every element - it's UILabel, I created class TimeViewCell: UITableViewCell where have property var labels = [UILabel]() but I don't know how to push data from my array in my function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
let showHour = self.infoWripper.sorted(by: { $0.hour < $1.hour })
cell.labelTime.text = showHour[indexPath.row].showHour()
for data in showHour {
print(data.showFullTime()) //here you see my example of data in console
}
return cell
}
I would add a UIStackView to your UITableViewCell. You can add the labels with the text to the UIStackView.
I wrapped your data into an array.
let tableViewData = [["06:58"],
["07:13", "07:38", "07:53"],
["08:13", "08:38", "08:53"],
["09:13", "09:33", "09:53"]]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
cell.configure(data: tableViewData[indexPath.row])
return cell
}
Then, in for your TimeViewCell, you have to add your UIStackView IBOulet (or add it programmatically) and the configure method.
class TimeViewCell: UITableViewCell {
#IBOutlet var labelStackView: UIStackView!
func configure(data: Array<String>) {
for time in data {
let timeLabel = UILabel()
timeLabel.text = time
labelStackView.addArrangedSubview(label)
}
}
}
In my first tableViewController has navigationViewController.push(myNextController, animated: true) and I want to segue to another TableViewController. What I am trying to figure out for hours is that when I select a row in my first tableViewController, I want to move to the next tableview. Right now, when I select a row, my next tableVIew has the same data. I want each cell to have differently saved cells
Second table view controller
The title is the navigation title and the myArray is an array:
// globally declared
var dataArray = [String]()
var myArray = [String]()
// this function is in my second table view controller, viewDidLoad()
func data(){
myArray = UserDefaults.standard.stringArray(forKey: "Key")!
dataArray = myArray
}
The dataArray is:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
if let getData = UserDefaults.standard.stringArray(forKey:"key") {
cell.textLabel?.text = getData[indexPath.row]
}
tableView.reloadData()
return cell
}
first table view controller
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
cell.backgroundColor = UIColorUtil.rgb(rgbValue: 0xFFFFF9)
let getData = UserDefaults.standard.stringArray(forKey: "category")!
let nextViewController = TableView()
nextViewController._titile = getData[indexPath.row]
// so I access myArray from second table view controller because I want to
//get data of each selected cell. But this is a problem.
nextViewController.myArray = getData
self.navigationController?.pushViewController(nextViewController, animated:true)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
if let getData = UserDefaults.standard.stringArray(forKey:"category") {
cell.textLabel?.text = getData[indexPath.row]
}
return cell
}
Why do they have the same cells? How am I able to accomplish this without using a storyboard? I want to programmatically write code. By the way, I am using UITabBar as well. Thanks!