Enable unique actions for each row in UITableView - swift

I have a small tableview of 7 rows. I would like to enable different actions for a press of each row.
For example, the row at index 0 would display another VC (without passing data). The row at index 0 would open a web URL, the next might be a share function, etc.
My biggest problem is the first case of send the user to another VC. Mostly because I don't know if I should enable a segue. And for all cases, I need to be able to specify a function for each row separately, therefore I would need to specify the proper index (0,1,2,etc).
How can I do this is Swift?

Here is a skeleton of code you need:
class ViewController: UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 2 }
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = String(describing: indexPath)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("Do action for row 0")
} else if indexPath.row == 1 {
print("Do action for row 1")
}
}
}

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).

didSelectRowAtIndexpath not responding to clicks

I'm making a revision app for high school students. In this view, the user should be able to select the units that they want to study for a certain subject, and the index path of the selected units will be stored in an int array and passed on to the next view for displaying images. Unfortunately, the didSelectRowAt method is not responding for some reason.
The delegate and data source are set correctly, I know that it is not getting called as I wrote a print statement in the function, and nothing was printed in the console when I click on any one the table cells.
var units = [String]()
var selectedRows = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return units.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "unitCell", for: indexPath) as! UnitCell
cell.textLabel?.text = units[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedRows.append(indexPath.row)
print(selectedRows)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! ImageView
destination.folderNames = selectedRows
}
I expect an int array of row indexes of selected cells. But right now it is just empty.
If the code your showing in your question is accurate, the signature of the didSelectRowAt method is incorrect. It should be:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Note the leading "_" for the first parameter. If your class is a UITableViewController, you'll also need to add an override keyword.
If your code is already using this signature, please update your question to reflect that.
Also, this leading code cannot be correct. Please update it to what you're actually using,
var units = String var selectedRows = Int
You should use delegate method
optional func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath)
Instead of your existing one
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath)
Try and share your results.
First thing is that your didSectRow is depricated so please use
below one
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Secondly You have to set your TableView Delegate to Self like below
tableView.delegate = self

Remove index from sidemenu user type wise

I have implemented side menu in tableview and now my scenario is like, I have to manage sidemenu options as user types
Let me show my code
var items = ["Social Media Post", "Messages", "Manage User","My Account","Information","Logout"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MenuTableViewCell
cell.lblTitle.text = items[indexPath.row]
cell.imgMenuLogo.image = image[indexPath.row]
print(User_type)
if User_type == 2{
items.remove(at: 0)
}
return cell
}
but now i want . to de like this
if user_type == "3"{
// Social Media , Messages And Manage User options i want to remove
}
I am not able to understand how to remove from index.
Try something like this:
override func viewDidLoad() {
super.viewDidLoad()
getList()
}
func getList(){
switch userType{
case 0:
items = ["UserTypeOne_Home","UserType_One Settings","etc"]
break
case 1:
items = ["UserTypeTwo_Home","UserType_Two Settings","etc"]
break
default:
break
}
self.tableView.reloadData()
}
extension ViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Some ID")
cell?.textLabel?.text = items[indexPath.row]
return cell!
}
}
Try not to change the array from within the cellForRowAt indexPath method using indexPath.row, that will not give you the result you want. Modulate the array from outside the protocol method overrides, and just call the reloadData() method.
Try to use enum of UserType and check type of current user than Make an array with default options available to every user and then append specific data in array according to user type. Hope it clarifies :)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MenuTableViewCell
cell.lblTitle.text = items[indexPath.row]
cell.imgMenuLogo.image = image[indexPath.row]
print(User_type)
if User_type == 2{
items.remove(at: 0)
}
return cell
}
This will work, But you have done a small mistake here.
You have removed from array after setting label. So you need to remove the item from array first then do set label.
Btw, I will not recommend this method as you need to add/remove from array for every cellForRowAt method.

Assigning an array count to a tableviewcell label

I have a posts array in which I'm returning all the posts from a PHP file. I'm trying to assign the number of posts to a label in a tableview cell. However, when I assign the number of posts to a label, I'm getting a nil value. Can anyone help with this?
var posts = [AnyObject]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else {
return posts.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InfoCell
print(posts.count)
cell.PostsLbl.text = String(posts.count)
return cell
}
}
It looks like you are getting posts async from PHP file and after you get them you reload only the second section.

tableview persisting cell image after reloading

I have a tableview with cells that when selected displays an image within the selected cell, this image then disappears when the cell is selected again, and so on. When i press a submit button the selected cells are remembered and the tableview reloads with new data. But when doing this all the new data loads but the selected cell image persists. I have tried calling tableView.reloadData() on the main queue but it still persists. The image also persists when i press the submit button several times.
Heres my code:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return currentQuestion.answers.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.height/CGFloat(currentQuestion.answers.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
setSelectedArray()
let cell: AnswersTableViewCell = tableView.dequeueReusableCell(withIdentifier: "answersTableViewCell") as! AnswersTableViewCell
let text = currentQuestion.answers[indexPath.row]
let isAnAnswer = currentQuestion.answerKeys[indexPath.row]
cell.answerTextLabel.text = text
cell.answerView.backgroundColor = UIColor.white.withAlphaComponent(0.5)
cell.contentView.sendSubview(toBack: cell.answerView)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell: AnswersTableViewCell = tableView.cellForRow(at: indexPath) as? AnswersTableViewCell {
if cell.answerImageView.image == nil {
cell.answerImageView.image = UIImage(named: "paw.png")
selected[indexPath.row] = true
} else {
cell.answerImageView.image = nil
selected[indexPath.row] = false
}
}
}
#IBAction func submitButtonWasPressed() {
if questionNumber < questions.count - 1 {
questionNumber += 1
setCurrentQuestion()
self.answersTableView.reloadData()
self.view.setNeedsDisplay()
}
}
Any help would be great. Thanks
You need to set the image back to its correct value in cellForRow. Cells in your table are reused between calls to reloadData, and since you're not touching the imageView, it's keeping its previous value. Looks to me like you want:
cell.answerImageView.image = selected[indexPath.row] ? UIImage(named: "paw.png") : nil
inside of tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath).