UITableViewCell Content Disappears - ios

I have a uiTableView with 3 cells that have a uiContextualAction implemented through the trailingSwipeActionsConfigurationForRowAt delegate method.
On tap of the uiContextualAction I display an actionSheet with two actions - delete and dismiss.
When the actionSheet is displayed without having pressed any action, the cell's content for all 3 cells, specifically a uiImageView suddenly disappears.
Is there something inherent to uiTableViews causing this? I placed breakpoints throughout the aforementioned flow but to no avail on how to remedy this. Any thoughts would be appreciated.
BEFORE presented actionSheet - ImageView (red background w/ blue gradient image) of UITableViewCell
AFTER on presented actionSheet - ImageView (red background w/o blue gradient image)
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .normal, title: "") { (action, view, completion) in
self.onDeleteCell(indexPath)
completion(true)
}
delete.backgroundColor = UIColor.red
delete.image = #imageLiteral(resourceName: "x_circle")
let config = UISwipeActionsConfiguration(actions: [delete])
config.performsFirstActionWithFullSwipe = false
return config
}
func onDelete(_ indexPath: IndexPath) {
AlertController.showActionSheet(self, title: nil, message: nil, actionOneTitle: "Delete", actionOneStyle: .destructive, actionTwoTitle: "Dismiss", actionTwoStyle: .cancel) { (_) in
self.updateCells(indexPath)
}
}
//From custom AlertController class
static func showActionSheet(_ inViewController: UIViewController, title: String?, message: String?, actionOneTitle: String, actionOneStyle: UIAlertAction.Style, actionTwoTitle: String, actionTwoStyle: UIAlertAction.Style, actionOneHandler: #escaping ((UIAlertAction) -> Void)) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
let actionOne = UIAlertAction(title: actionOneTitle, style: actionOneStyle, handler: actionOneHandler)
alert.addAction(actionOne)
let actionTwo = UIAlertAction(title: actionTwoTitle, style: actionTwoStyle, handler: nil)
alert.addAction(actionTwo)
inViewController.present(alert, animated: true, completion: nil)
}

Still unsure what the issue is/was...but I replaced the vector image as png and it appears to render and not suddenly vanish anymore..
Not a definitive solution, but it for now happens to work for me.

Related

How do I disable the default Delete swipe action and display my custom swipe action instead?

I'm implementing leading/trailing swipe actions in my app.
The leading swipe action is to join/leave an event in the table. The trailing swipe action is to delete an event. Both of these swipe actions should be conditional, based primarily on if the user is logged in or not.
If the user swipes left or right, and the user is not logged in, I want to display an alert ("Login required...").
If the user is logged in, the leading action will conditionally be titled "Leave" or "Join" depending on if the user has already joined the event or not. The trailing "Delete" action will be created only if the user is the also the creator of the event.
When I test the app and the user is logged in, everything works perfectly. (That was working before I decided to add the conditional element.)
When I test the app, and the user is not logged in, the leading swipe works perfectly: I swipe left (in my case), the alert pops up. No swipe action appears in the TableViewCell.
The trailing swipe also shows the alert and reacts correctly, but for some reason it's also showing a "Delete" action, even though my code uses the title "Blah". After dismissing the alert, the red "Delete" action is still visible and clickable.
I've also completely removed the "trailingSwipe..." method but the "Delete" action still appears, so I need to figure out where the default is so I can turn it off and/or override it.
How do I prevent the default Delete action from appearing and display my action instead?
Here's my code for the leading swipe:
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if currentUserID == nil {
showLoginRequiredMessage()
return nil
} else {
var userName = people.randomElement() // for testing
if event.eventMembers.contains(userName) {
let index = event.eventMembers.firstIndex(of: userName)!
let leaveAction = UIContextualAction(style: .normal, title: "Leave") { (action, view, nil) in
event.eventMembers.remove(at: index)
tableView.setEditing(false, animated: true)
tableView.reloadRows(at: [indexPath], with: .automatic)
self.saveEvents()
}
leaveAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [leaveAction])
} else {
let joinAction = UIContextualAction(style: .normal, title: "Join") { (action, view, nil) in
event.eventMembers.append(userName)
tableView.setEditing(false, animated: true)
tableView.reloadRows(at: [indexPath], with: .automatic)
self.saveEvents()
}
joinAction.backgroundColor = .green
return UISwipeActionsConfiguration(actions: [joinAction])
}
}
}
Here's my code for the trailing swipe:
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if currentUserID == nil {
showLoginRequiredMessage()
return nil
} else {
let trailingAction = UIContextualAction(style: .destructive, title: "Blah") { (action, view, nil) in
tableView.setEditing(false, animated: true)
print ("Delete this event")
}
trailingAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [trailingAction])
}
}
And here's the code for the alert:
private func showLoginRequiredMessage() {
let ac = UIAlertController(title: "Login Required", message: "To modify an event, you must first login", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Sign In", style: .default, handler: {(action) in
if let authenticationController = self.storyboard?.instantiateViewController(withIdentifier: "authenticationScreen") {
self.present(UINavigationController(rootViewController: authenticationController), animated: true)
}
}))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(ac, animated: true)
}
I have solved your issue. I hope that will work for you.
In trailingSwipeActions method change action style to normal, you will get "Blah" title.
Remove return nil from your if statement.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if currentUserID == nil {
self.showLoginRequiredMessage()
}
let trailingAction = UIContextualAction(style: .normal, title: "Blah") { (action, view, boolval) in
print ("Custom action event")
tableView.setEditing(false, animated: true)
}
trailingAction.backgroundColor = .gray
return UISwipeActionsConfiguration(actions: [trailingAction])
}
And, add .setEditing(false, animated: true) in below method
private func showLoginRequiredMessage() {
let ac = UIAlertController(title: "Login Required", message: "To modify an event, you must first login", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Sign In", style: .default, handler: {(action) in
self.myTableView.setEditing(false, animated: true)
if let authenticationController = self.storyboard?.instantiateViewController(withIdentifier: "authenticationScreen") {
self.present(UINavigationController(rootViewController: authenticationController), animated: true)
}
}))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {(action) in
self.myTableView.setEditing(false, animated: true)
}))
present(ac, animated: true)
}
Based on ChillY's answer to this question (Why is the leading swipe action also duplicated as a trailing action?), I realized the problem was that I was returning nil instead of UISwipeActionsConfiguration(actions: []).
Now I just have to figure out why the swipes are not disappearing after the action has been executed. Any ideas?

Swift 4, Background color goes white when deleting cell

I have found similar questions. None of which solve the same problem I am having.
This one here: Table view cell background goes white when deleting a cell - iOS
is in objective c. I need a swift answer.
I found this Change default background color while deleting a row from tableView
Answer in swift however when I add this to my code it still does not work.
Here is the code I am using to delete the cell.
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "delete") { (action, indexPath) in
let alertController = UIAlertController(title: "Warning", message: "Are you sure you want to delete this?", preferredStyle: .alert)
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) in
self.tableView.deleteRows(at: [indexPath], with: .fade)
})
alertController.addAction(deleteAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
return [delete]
}
I need to maintain the color of the cell as the delete option comes from swiping.
Thanks!
Reload the table after deleting cell and also remove cell data from the array as well or use this line in view did load
tableView.tableFooterView = UIView(frame: .zero)
this will remove the empty cell form table

UITableView RowActions : Do not dismiss row actions?

I have a tableview which uses two tableview row Actions one is delete and other is more.
When I tap on more button an alertcontroller is presented which has some actions.
I want that when morebutton is tapped the alertcontroller is presented but the rowActions remain there itself showing on which row the more button was pressed however it fades away as soon as I tap the more button.
Apple mail app and whatsapp do this successfully.
I am using xcode 9 and ios 11.1 in simulator.
I have used below code for implementing swipe to action functionality:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let conversation = fetchedResultsController.object(at: indexPath)
let conversationId = Int(conversation.id)
let conversationType = Int(conversation.conversation_type_id)
let deleteTitle = getDeleteRowActionTitle(conversationId: conversationId, conversationType: conversationType)
let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.normal, title: "More", handler:{action, indexpath in
self.moreAction(conversation: conversation, conversationId:conversationId,conversationType:conversationType,indexPath:indexpath)
})
moreRowAction.backgroundColor = UIColor.green
let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.destructive, title: deleteTitle, handler:{action, indexPath in
})
return [deleteRowAction, moreRowAction]
}
func moreAction(conversation:Nd_conversation,conversationId: Int,conversationType:Int,indexPath:IndexPath){
let muteTitle = notify ? "Mute" : "Unmute"
let moreActionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let action1 = UIAlertAction(title: muteTitle, style: .default, handler: {(action) -> Void in
})
moreActionSheet.addAction(action1)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(action) -> Void in })
moreActionSheet.addAction(cancelAction)
self.present(moreActionSheet, animated: true, completion: nil)
}
This is working in ios 10.3 but not in ios 11.

How can I create tableView in alertView with default values?

My code is this:
let alrController = UIAlertController(title: "Membri", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
tableView.backgroundColor = UIColor.white
alrController.view.addSubview(tableView)
let cancelAction = UIAlertAction(title: "Esci", style: UIAlertActionStyle.cancel, handler: {(alert: UIAlertAction!) in})
alrController.addAction(cancelAction)
self.present(alrController, animated: true, completion:{})
I want to populate (but I don't know how) the tableView with this values in my array: names["name1","name2","name3"]
Can someone help me?
To populate an action sheet, you don't add a tableView. Instead, you simply add the actions and it will create and manage the tableView privately.
For a recent tutorial, see UIAlertController Examples
The idea is that you'd create an UIAlertAction for each String in your array, including a closure for what to do when user taps that action row.
for name in names
{
let namedAction = UIAlertAction(title: name, style: .default)
{ (action) in
// do something when this action is chosen (tapped)
}
alrController.addAction(namedAction)
}
You need to implement the following tableView dataSource methods in order to populate this data and also set tableView datasource to alertController like below:-
tableView.dataSource = alertController
TableView DataSource method
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell: yourCustomCell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? yourCustomCell
else {
fatalError("yourCustomCell not found")
}
cell.textLabel.text = names[indexpath.row]
return cell
You can use custom UIViewController transition to achieve this kind of functionality.
This link: https://github.com/pgpt10/Custom-Animator will give you an idea of how you can achieve that.

UIButton not appearing on UITableViewCell

Alright, I am testing around a bit with core data, something I recently have started to discover, basically, what i have so far, is a single view app, that has a data source, and i can press a button and it brings up and alert, which from there i can add names to the list, and delete names from the list, i can close my app and still maintain my data. here is the issue/question, i am trying to do an update, so i can edit names in the list, i have a uibutton set up on my prototype cell, and i have it linked to my viewController, and have a function set inside the IBAction for the button. however, the button does not appear in my sim at run time.
here i have some code.
this is code for the edit button, and its function:
#IBAction func editButton(sender: AnyObject) {
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// 2
let alert = UIAlertController(title: "Update",
message: "Please enter the new name.",
preferredStyle: .Alert)
// 3
let updateAction = UIAlertAction(title: "Save",
style: .Default){(_) in
let nameTextField = alert.textFields![0]
self.updateName(indexPath.row, newName: nameTextField.text!)
self.tableView.reloadData()
}
// 4
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alert.addTextFieldWithConfigurationHandler(nil)
alert.addAction(updateAction)
alert.addAction(cancelAction)
// 5
self.presentViewController(alert, animated: true, completion: nil)
}
here is my cellForRowAtIndexPath func
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
let people = peoples[indexPath.row]
cell.textLabel!.text = people.name
return cell
}
here is an image of my storyboard
Storyboard
if you need further information or code, please let me know and i will provide it.

Resources