UITableViewCell sub class:
class MenuDrawerTableViewCell: UITableViewCell {
#IBOutlet weak var Label3: UILabel!
#IBOutlet weak var Image30: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}}
I have that class, now I got my viewController which has a table.
class OpenMenu: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableV: UITableView!
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
var selected = 0
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("prepare")
var DestVC = segue.destination as! CheckinController
var indexPath: NSIndexPath = self.tableV.indexPathForSelectedRow! as NSIndexPath
let menuItem = menuList[indexPath.row]
DestVC.varView = menuItem.index
}
let newSwiftColor = UIColor(red: CGFloat(255), green: CGFloat(0), blue: CGFloat(238), alpha: CGFloat(1))
var menuList = [Menu]()
func loadMenu() {
let photo1 = UIImage(named: "checkin")!
let menu1 = Menu(name: "Check In", photo: photo1, index: 20)!
let photo2 = UIImage(named: "checkin")!
let menu2 = Menu(name: "Add Store", photo: photo2, index: 10)!
menuList += [menu1, menu2]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuList.count // your number of cell here
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "MenuDrawerTableViewCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath as IndexPath) as! MenuDrawerTableViewCell
let menuItem = menuList[indexPath.row]
cell.Image30.image = menuItem.photo
cell.Label3.text = menuItem.name
cell.Label3.numberOfLines = 1;
if(0 == selected)
{
selected = 1
self.tableV.selectRow(at: indexPath, animated: true, scrollPosition: UITableViewScrollPosition.none)
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
// cell selected code here
print("cell selected")
print(indexPath)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuDrawerTableViewCell", for: indexPath as IndexPath) as UITableViewCell
return cell
}
#IBOutlet weak var Open: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
loadMenu()
self.tableV.delegate = self
self.tableV.dataSource = self
let size:CGFloat = 35.0 // 35.0 chosen arbitrarily
let preferences = UserDefaults.standard
let name1 = ""+preferences.string(forKey: "name")!
label2.text = name1
label1.text = String(name1[name1.startIndex])
label2.textColor = UIColor.white
label1.textColor = UIColor.white
label1.textAlignment = NSTextAlignment.center
label1.font = UIFont.systemFont(ofSize: 17)
label1.bounds = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: size, height: size))
label1.layer.cornerRadius = size / 2
label1.layer.borderWidth = 3.0
label1.layer.backgroundColor = newSwiftColor.cgColor
label1.layer.borderColor = UIColor.black.cgColor
}
override func viewDidAppear(_ animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}}
What I want, is detect the click on a tableview. But I am not able to detect anything .I supposedly should get cell selected printed, but i am getting nothing.Why the click function not getting called?
I think you need to selection of tableview as below :
You can check your code you have to implemented two time methods(cellForRowAtIndexPath and cellForRowAt)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
First make sure that you have connected tableview and connected delegate and datasource also.
Please remove these lines of code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuDrawerTableViewCell", for: indexPath as IndexPath) as UITableViewCell
return cell
}
As already you implemented this method.
Hope this will fix your problem.
I had this problem and noticed that somehow "isEditing" was set to "true" for the tableView in my viewDidLoad code... removing that line of code fixed it.
Related
What is the best practice to add dynamic list of items in UITableViewCell with showMore/showLess?
UITableView inside UITableViewCell
I used table view inside my UITableViewCell , but I have issue with reload row at indexPath causes jumpy scrolling.
TableViewController Code :
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource , delegatCell {
#IBOutlet weak var tableView: UITableView!
var elementsArray: [data] = []
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...20 {
elementsArray.append(data.init(title: "title\(i)", date: "8:00 PM", isShowMoreClicked: false, elements: ["ToDo\(i)","Aqraa\(i)","ToDo\(i)","ToDo\(i)" , "Mobile Team\(i)" , "Testing Data\(i)"]))
// Do any additional setup after loading the view, typically from a nib.
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elementsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let obj = elementsArray[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! expandedTableViewCell
cell.initializeCell()
print(obj.elements)
cell.data = obj.elements
cell.delegate = self
cell.dateLabel.text = obj.date
cell.titleLabel.text = obj.title
cell.showMore.titleLabel?.font = reqularDynamicFont()
cell.showMore.titleLabel?.adjustsFontSizeToFitWidth = true
cell.showMore.tag = indexPath.row
cell.isShowMoreClicked = obj.isShowMoreClicked
cell.tableView.reloadData()
self.view.layoutIfNeeded()
return cell
}
func reqularDynamicFont()-> UIFont{
let font = UIFont.systemFont(ofSize: 15, weight: .regular)
let fontMetrics = UIFontMetrics(forTextStyle: .caption1)
return fontMetrics.scaledFont(for: font)
}
func reloadTableView(indexpath: IndexPath , isShowMoreClicked: Bool) {
elementsArray[indexpath.row].isShowMoreClicked = isShowMoreClicked
tableView.reloadRows(at: [indexpath], with: .automatic)
}
}
ExpandedTableViewCell with inner table view Code :
import UIKit
protocol delegatCell {
func reloadTableView(indexpath: IndexPath , isShowMoreClicked: Bool)
}
class expandedTableViewCell: UITableViewCell , UITableViewDelegate , UITableViewDataSource{
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var showMore: UIButton!
var data : [String] = []
var initalNum = 2
var isShowMoreClicked: Bool = false
var delegate:delegatCell?
func initializeCell(){
data.removeAll()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isShowMoreClicked{
return data.count
}else{
return initalNum
}
}
#IBAction func reloadData(_ sender: UIButton) {
delegate?.reloadTableView(indexpath: IndexPath(row: sender.tag, section: 0), isShowMoreClicked: !isShowMoreClicked)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(data)
let cell = tableView.dequeueReusableCell(withIdentifier: "simpleTableViewCell", for: indexPath) as! simpleTableViewCell
cell.descLabel.text = data[indexPath.row]
return cell
}
}
I used auto layout to support dynamic height.
How to slide out the side menu bar when I swipe to the left? and how will it automatically slide out when I click the collectionView? I'm using tableView and constraints, my outlet to that constraint is rightMargin.
import UIKit
import ViewPagerController
class OptionTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var rightMargin: NSLayoutConstraint!
#IBOutlet weak var optionTableView: UITableView!
let option = ["LOG IN","SIGN UP","EDIT PROFILE", "LOG OUT"]
let storyBoardId = ["LogInViewController","SignUpViewController","UserEditPageViewController", "None"]
override func viewDidLoad() {
super.viewDidLoad()
var appearance = ViewPagerControllerAppearance()
appearance.tabMenuAppearance.backgroundColor = UIColor.black
let screenWidth = UIScreen.main.bounds.width
rightMargin.constant = screenWidth
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.rightMargin.constant = 100
UIView.animate(withDuration: 0.3 , animations: {
self.view.layoutIfNeeded()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return option.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = optionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = option[indexPath.row]
cell.textLabel?.font = UIFont(name: "Arial", size: 10)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let logInViewController = storyboard?.instantiateViewController(withIdentifier: storyBoardId[indexPath.row]) {
navigationController?.pushViewController(logInViewController, animated: true)
}
}
}
SlideInMenu
These will let you slide to open up your own options.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, editActionsForRowAt: IndexPath) -> [UITableViewRowAction]? {
let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
print("more button tapped")
}
more.backgroundColor = .lightGray
let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
print("favorite button tapped")
}
favorite.backgroundColor = .orange
let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
print("share button tapped")
}
share.backgroundColor = .blue
return [share, favorite, more]
}
Can anyone see why in the world didSelectRowAtIndexPath would not be called? I have triple checked by delegate both in the code and in storyboard.
class AddCard: UIViewController,UIPopoverPresentationControllerDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var cardView: UIView!
#IBOutlet weak var tableView: UITableView!
let tableItems = ["Background Color","Background Image","Font Style","Font Color"]
let cellID = "cell"
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setBackgroundColor (_ color: UIColor) {
cardView.backgroundColor = color
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath as IndexPath)
let row = indexPath.row
cell.textLabel?.text = tableItems[row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
print(indexPath.row)
let row = indexPath.row
switch(row){
case 0:
let popoverVC = storyboard?.instantiateViewController(withIdentifier: "colorPickerVC") as! ColorPickerViewController
popoverVC.modalPresentationStyle = .popover
popoverVC.preferredContentSize = CGSize(width: 284, height: 446)
if let popoverController = popoverVC.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: 0, y: 0, width: 85, height: 30)
popoverController.permittedArrowDirections = .any
popoverController.delegate = self
popoverVC.delegate = self
}
present(popoverVC, animated: true, completion: nil)
break
default: break
}
}
}
Swift 3 modified the signature of the method (a lot of methods too, new "rules"/style)
Replace:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) with
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Notice the _, the didSelectRowAt vs didSelectRowAtIndexPath, like the other ones you updated (which adapted also the same "style"), but not this one.
Remove the line and let XCode do the autocompletion. Else, you can just replace it with the one from the doc.
I made an app with UITableView. I want to show a tick mark in the left when cell is touched, and to be hidden when again is touched. I used some code and It's not showing as I wanted. The tick is showing on the right not on the left of screen.
This is how I want to make:
This is how it is:
And here is code that I used:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.allowsMultipleSelection = true
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.None
}
In conclusion, first problem is that the tick is showing on the right of the cell and not on the left. And the other problem, it won't untick (hide when cell is pressed again)
Thanks.
Try this
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "DhikrTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! GoalsTableViewCell
cell.tickButton.addTarget(self, action: #selector(GoalsViewController.toggleSelcted(_:)), forControlEvents: UIControlEvents.TouchUpInside)
cell.tickButton.tag = indexPath.row
// Fetches the appropriate meal for the data source layout.
let workout = workouts[indexPath.row]
let number = numbers[indexPath.row]
if workout.isSelected {
cell.tickButton.setImage(UIImage(named: "Ticked Button"), forState: UIControlState.Normal)
} else {
cell.tickButton.setImage(UIImage(named: "Tick Button"), forState: UIControlState.Normal)
}
cell.nameLabel.text = workout.name
cell.numberLabel.text = number.number
return cell
}
func toggleSelcted(button: UIButton) {
let workout = workouts[button.tag]
workout.isSelected = !workout.isSelected
myTableView.reloadData()
}
To achieve this behavior with default UITableViewCell, you may need to set table view to edit mode.
Try the following code in your viewDidLoad.
self.tableView.allowsMultipleSelectionDuringEditing = true
self.tableView.setEditing(true, animated: false)
This will show tick mark on the left side, and also this will untick (hide) when cell is pressed again.
Edited:
If you need more customization, Create a custom table view cell and handle the selection/tick mark manually.
This will be your cell.swift.
class CustomCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tickImageView: UIImageView!
//Handles the cell selected state
var checked: Bool! {
didSet {
if (self.checked == true) {
self.tickImageView.image = UIImage(named: "CheckBox-Selected")
}else{
self.tickImageView.image = UIImage(named: "CheckBox-Normal")
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
checked = false
self.layoutMargins = UIEdgeInsetsZero
self.separatorInset = UIEdgeInsetsZero
}
The datasource array is,
let list = ["Title 1", "Title 2", "Title 2", "Title 4"]
The view controller didLoad will be like
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
listView.registerNib(UINib(nibName: "OptionsSelectionCell", bundle: nil), forCellReuseIdentifier: "SelectionCell")
}
The view controller table delegate methods will be like,
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SelectionCell") as! OptionsSelectionCell
cell.titleLabel.text = list[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! OptionsSelectionCell
cell.checked = !cell.checked
}
}
I would like to add a picker view at the footer of the app when I tap the cell and change the Detail label with the picker view data. I would like to do the same think with the DatePicker, but only in one cell ( the one named Service appt. Date).
This is my code:
import UIKit
class Service2Appointment: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var TableView: UITableView!
#IBOutlet weak var pickerView: UIPickerView!
let FormName = ["State","City","Vehicle Reg Number","Location","Current Kms","Service appt. Date","Service appt. Type","Pick-up Vehicle","Discount Code","Service Notes"]
let textCellIdentifier = "TextCell"
override func viewDidLoad() {
super.viewDidLoad()
pickerView.hidden = true
TableView.delegate = self
TableView.dataSource = self
self.TableView.rowHeight = 70
TableView.backgroundView = UIImageView(image: UIImage(named: "background.png"))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UITextFieldDelegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FormName.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = TableView.dequeueReusableCellWithIdentifier(FormName[indexPath.row], forIndexPath: indexPath) as! UITableViewCell
if (indexPath.row % 2 == 0) {
cell.backgroundColor = UIColor.clearColor()
}else{
cell.backgroundColor = UIColor.clearColor()
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
let row = indexPath.row
cell.detailTextLabel?.text = FormName[row]
cell.textLabel?.text = FormName[row]
cell.textLabel?.textColor = UIColor.whiteColor()
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
TableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
println(FormName[row])
}
}