Perform action when UITableViewCell is clicked - swift

I am making an tvOS app for the Apple TV but I have some problems with my UITableView.
When I click on a UITableViewCell nothing happens. I am using targetForAction but it doesn't seem to work.
This is my code:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
}
let allData = ["Los Angeles","New York","San Fransisco"]
#IBOutlet weak var tableView: UITableView!
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .Default, reuseIdentifier: nil)
cell.textLabel?.text = "\(allData[indexPath.row])"
cell.targetForAction("buttonClicked:", withSender: self)
return cell
}
func buttonClicked(sender:AnyObject) {
print("button clicked!")
}

I found the solution.
I had to add this function:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("selected cell \(indexPath.row)")
}

Swift 5:
func tableView(_ tableView: UITableView, didSelectRowAtindexPath indexPath: IndexPath) {
print(indexPath.row)
}

Please use the UITableView Delegate method.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}

Related

How to change editing style for specific cell in tableview

I have a tableview where the editingstyle is .delete for all the cells. But I want to have some specific cells that doesnt have editingstyle (so that you can't swipe them, .none). Anyone have any suggestions for how to implement this?
I tried to write something like UITableViewCell.EditingStyle.none for that specific row but that didnt work.
Thanks in advance, Pontus
Consider the following example:
class ViewController: UITableViewController {
private let arr = (1...10).map { "Item \($0)" }
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel?.text = arr[indexPath.row]
return cell ?? UITableViewCell()
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
if indexPath.row == 2 {//<- Your condition
return .none
} else {
return .delete
}
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
}
So the key is to use editingStyleForRowAt in order to change the style for a specific cell (or even multiple cells) (see the documentation for further reference: https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614869-tableview).

Disable users to scroll up in tableView?

Similar to tinder, if a user goes down, I don't want them to be able to go back upwards. How do I do this?
I tried the code below, but it keeps running an error: Index out of range.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! FeedTableViewCell
cell.collectionView.delegate = self
cell.collectionView.dataSource = self
//reloading the tableview
let artist: UserModel
artist = self.userList[indexPath.row]
cell.nameLabel.text = artist.name
cell.passionLabel.text = artist.passion
cell.collectionView.reloadData()
if indexPath.row == 1 {
userList.removeFirst()
}
return cell
}
Refer below code,
You need to store last scroll Content Offset of tableview, when user scroll down, refer scrollViewDidScroll method.
#IBOutlet weak var tableView: UITableView!
var lastContentOffsetY:CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.bounces = false
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuse")
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 50
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuse")
return cell!
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if(scrollView.contentOffset.y < self.lastContentOffsetY){
self.tableView.setContentOffset(CGPoint(x:scrollView.contentOffset.x, y: self.lastContentOffsetY), animated: false)
}else{
self.lastContentOffsetY = scrollView.contentOffset.y
}
}

TableView action per item

I have a tableView like this:
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
let names = ["TEXT1", "TEXT2", "TEXT3"]
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewControllerMeer: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let name = names[indexPath.row]
print("You clicked on \(name)")
}
}
extension ViewControllerMeer: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = names[indexPath.row]
let n = names[indexPath.item]
switch n {
case "TEXT1":
print("s1")
case "TEXT2":
print("s2")
case "TEXT3":
print("s3")
default:
break
}
return cell
}
}
It reads the items from the 'let names', So far so good :) I now want to add some actions because now every item will print 'You tapped me'. I figured something out like
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if indexPath.row == 0 {
print("cell1")
} else if indexPath.row == 1 {
print("cell2")
} else if indexPath.row == 2 {
print("cell3")
}
}
The only problem is that it generates an error 'Method does not override any method from its superclass'. So I guess this won't work. What would be a good method to do it?
remove the override in front of func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
And you can either to a big if statement or switch statement to do something with the names or you can do something like:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let name = names[indexPath.row]
print("You clicked on \(name)")
switch indexPath.row {
case 0:
//do something
self.shareApp()
case 1:
//do something else
self.writeReview()
default:
break
}
}
I just copied your codes to show you basically if you really want to override tableview functions
class ViewController: UITableViewController {
#IBOutlet var tableView: UITableView!
let names = ["TEXT1", "TEXT2", "TEXT3"]
override func viewDidLoad() {
super.viewDidLoad()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped me!")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = names[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let name = names[indexPath.row]
print("You clicked on \(name)")
}
}

Action when tap on tableViewCell (swift)

I want execute a code when user tap on tableViewCell, this is the code:
import UIKit
import MediaPlayer
class ViewController: UIViewController, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titolo.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier")!
let text1 = titolo[indexPath.row]
let text2 = genere[indexPath.row]
cell.textLabel?.text = text1
cell.detailTextLabel?.text = text2
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("test tap cell")
}
#IBOutlet weak var tableView: UITableView!
let mediaItems = MPMediaQuery.songs().items
let musicPlayer = MPMusicPlayerApplicationController.applicationQueuePlayer
...
This function not work:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("test tap cell")
}
"test tap cell" does not appear in the console.
You need to set delegate and dataSource and implement didSelectRowAt correctly
class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tableView.delegate = self
self.tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titolo.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier")!
cell.textLabel?.text = text1
cell.detailTextLabel?.text = text2
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("test tap cell")
}
}

Make Cell Clickable In UIViewController

I am using a UIViewController and a Table View/Table View Cell (extending to delegate/datasource). Whenever a cell is clicked from MessageController, it is supposed to be directed into another View Controller, called ChatController. Even though I am using didSelectRowAt and adding a segue with identifier, it does not switch to the ChatController.
import UIKit
class MessagesController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var myIndex = 0;
#IBOutlet weak var tableView: UITableView!
var tableData: [MModel] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
MData.getData { (data) in
self.tableData = data
self.tableView.reloadData()
}
func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell") as! MessagesCell
cell.setup(model: tableData[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 375
}
//clicking on cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segue", sender: nil)
}
}
The problematic line is as follows:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segue", sender: nil)
}
You must set the delegate also in viewDidLoad
self.tableView.delegate = self
You have not set the delegate to the tableview.
Set it as:
aftertableView.dataSource = self
tableView.delegate = self
my problem had to do with having a GestureRecognizer in my viewDidLoad(). after so many hours of troubleshooting i realize that what was breaking the code was that 'hide keyboard' code of GestureRecognizer.