Swipe to delete with multiple options - ios

When the user swipes a table view cell in the chat view controller I would like to offer the option to either Block and delete that user, or to only delete the chat from the user. Is there a way I can have the swipe to delete option to have both options available? Should I be adding the block user option on a different page or will there be a way to have both in the commit editingStyle function.
class Conversation {
var key:String
var sender:String
var recipient:String
var date:Date
var recentMessage:String
var seen:Bool
init(key:String, sender: String, recipient:String, date:Date, recentMessage:String, seen:Bool) {
self.key = key
self.sender = sender
self.recipient = recipient
self.date = date
self.recentMessage = recentMessage
self.seen = seen
}
// Returns the UID of the conversations partner
// i.e NOT the UID of the current user
var partner_uid:String {
guard let uid = Auth.auth().currentUser?.uid else { return "" }
if sender != uid {
return sender
}
return recipient
}
func printAll() {
print("key: \(key)")
print("sender: \(sender)")
print("recentMessage: \(recentMessage)")
}
}
class ChatsTableViewController:UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView:UITableView!
var conversations = [Conversation]()
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: view.bounds)
let nib = UINib(nibName: "ChatTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "chatCell")
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
title = "CHAT"
view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let cell = tableView.cellForRow(at: indexPath) as! ChatTableViewCell
let name = cell.usernameLabel.text!
let actionSheet = UIAlertController(title: "Block conversation with \(name)?", message: "Further messages from \(name) will be muted.", preferredStyle: .alert)
let cancelActionButton: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in }
actionSheet.addAction(cancelActionButton)
let deleteActionButton: UIAlertAction = UIAlertAction(title: "Block", style: .destructive)
{ action -> Void in
self.muteConversation(self.conversations[indexPath.row])
}
let deleteOnlyButton: UIAlertAction = UIAlertAction(title: "Only Delete", style: .destructive)
{ action -> Void in
print("only delete selected ")
}
actionSheet.addAction(deleteActionButton)
actionSheet.addAction(deleteOnlyButton)
self.present(actionSheet, animated: true, completion: nil)
}
}
func muteConversation(_ conversation:Conversation) {
guard let user = Auth.auth().currentUser else { return }
let ref = Database.database().reference()
let obj = [
"social/blocked/\(user.uid)/\(conversation.partner_uid)" : true,
"social/blockedBy/\(conversation.partner_uid)/\(user.uid)" : true,
"conversations/users/\(user.uid)/\(conversation.partner_uid)/muted": true
] as [String:Any]
print("OBBJ: \(obj)")
ref.updateChildValues(obj, withCompletionBlock: { error, ref in
if error != nil {
let alert = UIAlertController(title: "Error deleting conversation!", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
} else {
let alert = UIAlertController(title: "Conversation blocked!", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
}
})
}
}

Try this code and replace Action1 & Action2 with your preferred actions.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: {
(action, indexPath) in
print("Action1")
})
action1.backgroundColor = UIColor.lightGray
let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: {
(action, indexPath) in
print("Action2")
})
return [action1, action2]
}

Download/Refer https://github.com/CEWendel/SWTableViewCell/archive/master.zip, integrate this third party library to your project and try the below code in your ViewController
Step 1:
add the delegate SWTableViewCellDelegate to your ViewController
Step 2:
in your cellForRow
cell.leftUtilityButtons = leftButtons() as [AnyObject]
cell.rightUtilityButtons = self.rightButtons() as [AnyObject]
cell.delegate = self;
Step 3:
customise your left/right side buttons on swipes
func leftButtons() -> NSMutableArray
{
let leftUtilityButtons : NSMutableArray = NSMutableArray()
leftUtilityButtons.sw_addUtilityButton(with: UIColor.orange, title: "Block")
leftUtilityButtons.sw_addUtilityButton(with: UIColor.green, title: "Remove User")
return leftUtilityButtons
}
func rightButtons() -> NSMutableArray {
let leftUtilityButtons : NSMutableArray = NSMutableArray()
leftUtilityButtons.sw_addUtilityButton(with: UIColor.red, title: "Delete Chat")
return leftUtilityButtons
}
Step 4:
handle actions with these two delegate methods
// click event on left utility button
func swipeableTableViewCell(_ cell: SWTableViewCell, didTriggerLeftUtilityButtonWith index: Int)
{
switch index
{
case 0:
// Handle your button1 action (Block User)
break
case 1: break
// Handle your button2 action (Remove User)
default:
break
}
}
// click event on right utility button
func swipeableTableViewCell(_ cell: SWTableViewCell, didTriggerRightUtilityButtonWith index: Int)
{
//handle your right button action (Delete Chat)
}
Thats it...!

You can modify your function like this to work
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let blockAction = UITableViewRowAction(style: .normal, title: "Block") { (rowAction, indexPath) in
self.muteConversation(self.conversations[indexPath.row])
}
let deleteAction = UITableViewRowAction(style: .destructive, title: "Only Delete") { (rowAction, indexPath) in
print("only delete selected ")
}
blockAction.backgroundColor = UIColor.gray
return [blockAction, deleteAction]
}
and if you want to show action sheet instead you can use this code
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let moreAction = UITableViewRowAction(style: .normal, title: "More") { (rowAction, indexPath) in
self.showActionSheet(indexPath)
}
moreAction.backgroundColor = UIColor.blue
return [moreAction]
}
func showActionSheet(_ indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! ChatTableViewCell
let name = cell.usernameLabel.text!
let actionSheet = UIAlertController(title: "Block conversation with \(name)?", message: "Further messages from \(name) will be muted.", preferredStyle: .alert)
let cancelActionButton: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in }
actionSheet.addAction(cancelActionButton)
let deleteActionButton: UIAlertAction = UIAlertAction(title: "Block", style: .destructive)
{ action -> Void in
self.muteConversation(self.conversations[indexPath.row])
}
let deleteOnlyButton: UIAlertAction = UIAlertAction(title: "Only Delete", style: .destructive)
{ action -> Void in
print("only delete selected ")
}
actionSheet.addAction(deleteActionButton)
actionSheet.addAction(deleteOnlyButton)
self.present(actionSheet, animated: true, completion: nil)
}

Related

How do I delete CoreData entries in a tableview that uses a persistentcontainer?

I am designing an app where users will key in information in an alert view with multiple textfields. These strings will then be combined and be saved in an attribute of an entity (as one entity). This will then be displayed in a tableview.
Now I would implement a way to delete entries should the user enter something wrong.
I have seen many places where they say use the following code to delete entries in CoreData:
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
let managedObjectContext = coreData.persistentContainer.viewContext
if editingStyle == .delete
{
movieToDelete = fetchedResultController.object(at: indexPath)
let confirmDeleteAlertController = UIAlertController(title: "Remove Movie", message: "Are you sure you would like to delete \"\(movieToDelete!.title!)\" from your movie library?", preferredStyle: UIAlertControllerStyle.actionSheet)
let deleteAction = UIAlertAction(title: "Delete", style: UIAlertActionStyle.default, handler: { [weak self] (action: UIAlertAction) -> Void in
managedObjectContext.delete((self?.movieToDelete!)!)
self?.coreData.saveContext()
self?.movieToDelete = nil
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { [weak self] (action: UIAlertAction) -> Void in
self?.movieToDelete = nil
})
confirmDeleteAlertController.addAction(deleteAction)
confirmDeleteAlertController.addAction(cancelAction)
present(confirmDeleteAlertController, animated: true, completion: nil)
}
}
However, I was following a tutorial on youtube and as a result I do not have a ManagedObjectContext in my code to make use of the editingStyle.delete. Now I am stuck as to how to delete an entry. Do I change my earlier code to support a ManagedObjectContext or is there a way to delete the entries through persistent container?
This is the code in my viewController which I feel is important to the issue at hand:
class ViewController: UITableViewController {
var alarmItems: [NSManagedObject] = []
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "AlarmItems")
do {
alarmItems = try managedContext.fetch(fetchRequest)
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
#objc func addAlarmItem(_ sender: AnyObject) {
print("this works")
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
//combined string of attributes
let myStrings: [String] = alertController.textFields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ", ")
self.save(myText)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "Enter Name of Engineer"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Please indicate True/False (type True or False)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Insert comments (if any), or NIL"
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItems", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
alarmItems.append(item)
} catch let err as NSError {
print("Failed to save an item", err)
}
}
#objc func exportCSV(_ sender: AnyObject) {
//will work on exporting csv in the future
return
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return alarmItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = alarmItems[indexPath.row]
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
/*
//create delete feature
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath ) {
if editingStyle == UITableViewCell.EditingStyle.delete {
}
}
*/
}
As you are using NSFetchedResultsController delete the data source array
var alarmItems: [NSManagedObject] = []
and all other occurrences of alarmItems. The NSFetchedResultsController instance becomes the data source array
In viewWillAppear just refetch the data
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
do {
try fetchedResultsController.performFetch()
tableView.reloadData()
} catch {
print(error)
}
}
Replace the datasource and delegate methods with
override func numberOfSections(in tableView: UITableView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = fetchedResultsController.object(at: indexPath) as! NSManagedObject
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
Now your delete method is supposed to work.
Note:
You are encouraged to use always the NSManagedObject subclass AlarmItems ( by the way semantically each Core Data record represents one AlarmItem) and dot notation for example
let alarmItem = fetchedResultsController.object(at: indexPath) as! AlarmItem
cell.textLabel?.text = alarmItem.alarmAttributes

How to edit row in tableView and save changes in the coreData?

I created a simple toDoList with a simple coreData. Added creating a row, deleting a row, but can't change the row.
I can't understand how to do it.
I added alertСontroller to change it.
My coreData consists of one property: name.
And I make an interface without a storyboard, just code.
How to update a CoreData object?
import UIKit
import CoreData
class ViewController: UITableViewController {
private let cellID = "cell"
private var tasks = [Task]()
private let appDelegate = UIApplication.shared.delegate as! AppDelegate //
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "To do list"
navigationController?.navigationBar.barTintColor = UIColor(displayP3Red: 21/255,
green: 101/255,
blue: 192/255,
alpha: 1)
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add",
style: .plain,
target: self,
action: #selector(addNewTask))
navigationController?.navigationBar.tintColor = .white
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
do {
tasks = try managedContext.fetch(fetchRequest)
} catch let error {
print("Failed to fetch data", error)
}
}
// MARK: Table View Data Source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
let task = tasks[indexPath.row]
cell.textLabel?.text = task.name
return cell
}
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let editNotesAction = UITableViewRowAction(style: .default, title: "Edit") { (action: UITableViewRowAction, indexPath: IndexPath) in
let alert = UIAlertController(title: "Edit", message: "", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default, handler: { (action) in
})
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
self.present(alert, animated: true)
}
editNotesAction.backgroundColor = .blue
let deleteNotesAction = UITableViewRowAction(style: .default, title: "Delete") { (action: UITableViewRowAction, indexPath: IndexPath) in
let managedContext = self.appDelegate.persistentContainer.viewContext
managedContext.delete(self.tasks[indexPath.row])
self.tasks.remove(at: indexPath.row)
do {
try managedContext.save()
} catch let error {
print(error.localizedDescription)
}
self.tableView.deleteRows(at: [indexPath], with: .fade)
}
return [deleteNotesAction, editNotesAction]
}
#objc private func addNewTask() {
let alert = UIAlertController(title: "New Task", message: "", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { _ in
guard let task = alert.textFields?.first?.text, task.isEmpty == false else { return }
self.saveData(task)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
private func saveData(_ taskName: String) {
let managedContext = appDelegate.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName: "Task", in: managedContext) else { return }
let task = NSManagedObject(entity: entity, insertInto: managedContext) as! Task
task.name = taskName
do {
try managedContext.save()
tasks.append(task)
} catch let error {
print("Failed to save task", error.localizedDescription)
}
}
}
Your save action needs to take the value out of the text field and assign it to the right managed object.
let saveAction = UIAlertAction(title: "Save", style: .default, handler: { (action) in
guard let textField = alert.textFields.first else { return }
let task = tasks[indexPath.row]
task.name = textField.text
})
If name is not optional you will need to use nil-coalescing to supply a default value for the name in case the text field is empty. (task.name = textField.text ?? "SomeDefaultName")

iOS Swift 3: does retain cycle happens in this case?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CheckoutCell") as! CheckoutCell
let product = shoppingCart[indexPath.row]
var tfQuantity : UITextField!
cell.clickEditAction = { [weak self] celll in
guard let ss = self else { return }
let alert = UIAlertController(title: nil, message: "Enter new quantity", preferredStyle: .alert)
alert.addTextField { (textfield) in
tfQuantity = textfield
}
let okAction = UIAlertAction(title: "OK", style: .default) { (action) in
if tfQuantity.text == ""{
return
}
if let newQuantity = Int(tfQuantity.text){
product.quantity = newQuantity
self.tbvCheckout.reloadData()
}
return
}
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
return cell
}
This line of code:
self.tbvCheckout.reloadData()
If I don't use [weak self] or [unowned self], does it create retain cycle between current object & UIAlertAction instance?
What if I use this code instead: tableView.reloadData()?
Couple of things:
First, You have created a weak reference, but I don't see you using it in the code.
guard let ss = self else { return }
Any reference to self should be via this weak self variable "ss" that you have created.
Second, The alert action block should also have weak reference to self
let okAction = UIAlertAction(title: "OK", style: .default) { [weak self] (action) in
if tfQuantity.text == ""{
return
}
if let newQuantity = Int(tfQuantity.text){
product.quantity = newQuantity
self?.tbvCheckout.reloadData()
}
return
}

Unable to display table view on Swift 3

I’m currently trying to load out my tableview using these codes, however I get a thread breakpoint at return listitem.count. Any help to solve this problem would be great.
The following below are my codes:
import UIKit
import CoreData
class ViewInventoryTableController: UITableViewController{
var listItems = [NSManagedObject]()
override func viewDidLoad(){
super.viewDidLoad()
//Do any additional setup after loading the view, typically from a nib.
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.add, target: self, action: #selector(ViewInventoryTableController.addItem))
}
func addItem(){
let alertMessage = "Please key in the activation code"
let alertController = UIAlertController(title: "Add Item", message: alertMessage as String, preferredStyle: .alert)
//Add the textfield
var activationCodeTextField1: UITextField?
alertController.addTextField { (textField) -> Void in
activationCodeTextField1 = textField
activationCodeTextField1?.placeholder = "123456789"
}
// Create Cancel button
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction!) in
print("Cancel button tapped")
}
alertController.addAction(cancelAction)
// Create ConfirmAction
let confirmAction = UIAlertAction(title: "Confirm", style: UIAlertActionStyle.default, handler: ({
(_) in
if let field = alertController.textFields![0] as? UITextField{
self.saveItem(itemToSave: field.text!)
self.tableView.reloadData()
}
}
))
alertController.addAction(confirmAction)
// Present Dialog message
OperationQueue.main.addOperation {
self.present(alertController, animated: true){}
}
print("Activation Code = \(activationCodeTextField1?.text)")
}
//function save item
func saveItem(itemToSave: String){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "ListEntity", in: managedContext)
let item = NSManagedObject(entity: entity!, insertInto: managedContext)
item.setValue(itemToSave, forKey: "item")
do {
try managedContext.save()
listItems.append(item)
}
catch {
print("error")
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.right)
managedContext.delete(listItems[indexPath.row])
listItems.remove(at: indexPath.row)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of any resources that can be recreated
}
override func tableView (_ tableView: UITableView , numberOfRowsInSection section: Int) -> Int {
return listItems.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! as UITableViewCell
let item = listItems[indexPath.row]
cell.textLabel?.text = item.value(forKey: "item") as? String
return cell
}
}

UITableView will not refresh once list is deleted. self.tableView.reloadData() does not work either

I'm relatively new to developing Swift and iOS, but not new to code. I'm a little annoyed with the table view.
I have tried countless times to use self.tableView.reloadData() but to no avail. I have also tried
async call dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
But this doesn't want to work either. I'll post function so that maybe someone can enlighten me where I goofed up. I really do appreciate the help.
#IBAction func clearList(sender: AnyObject) {
let alert = UIAlertController(title: "Clear List?",
message: "Are you sure you want to clear the list?",
preferredStyle: .Alert)
let yesClearAction = UIAlertAction(title: "Yes", style: .Default, handler: { (action:UIAlertAction) -> Void in
self.clearListNow("GroceryList")
})
let noClearAction = UIAlertAction(title: "No", style: .Default, handler: { (action:UIAlertAction) -> Void in
//do nothing aka don't clear list
})
alert.addAction(yesClearAction)
alert.addAction(noClearAction)
presentViewController(alert, animated: true, completion: nil)
self.tableView.reloadData()
}
And just in case anyone wanted to see what clearListNow does...
func clearListNow(entity: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "GroceryList")
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
}
} catch let error as NSError {
print("Detele all data in \(entity) error : \(error) \(error.userInfo)")
}
}
I have also tried to use self.tableView.reloadData() in the clearListNow function. I have tried to place the statement in both at the same time, and separately and neither scenario worked.
Reload your tableView when use press Yes in your alert as shown into below code:
let yesClearAction = UIAlertAction(title: "Yes", style: .Default, handler: { (action:UIAlertAction) -> Void in
self.clearListNow("GroceryList")
self.tableView.reloadData()
})
try to reload data in yesClearAction
you should have something like :
#IBAction func clearList(sender: AnyObject) {
let alert = UIAlertController(title: "Clear List?",
message: "Are you sure you want to clear the list?",
preferredStyle: .Alert)
let yesClearAction = UIAlertAction(title: "Yes", style: .Default, handler: {(action:UIAlertAction) -> Void in
self.clearListNow("GroceryList")
self.tableView.reloadData()
})
let noClearAction = UIAlertAction(title: "No", style: .Default, handler: { (action:UIAlertAction) -> Void in
//do nothing aka don't clear list
})
alert.addAction(yesClearAction)
alert.addAction(noClearAction)
presentViewController(alert, animated: true, completion: nil)
}
Let me know if this works ! :)
UPDATE
I have done this code and it works fine for me
import UIKit
class ViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
var rows: NSMutableArray!
override func viewDidLoad() {
super.viewDidLoad()
self.rows = ["1","2","3","4","5","6","7"]
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func clearList(sender: AnyObject) {
let alert = UIAlertController(title: "Clear List?",
message: "Are you sure you want to clear the list?",
preferredStyle: .Alert)
let yesClearAction = UIAlertAction(title: "Yes", style: .Default, handler: { (action:UIAlertAction) -> Void in
self.clearListNow("GroceryList")
self.tableView.reloadData()
})
let noClearAction = UIAlertAction(title: "No", style: .Default, handler: { (action:UIAlertAction) -> Void in
//do nothing aka don't clear list
})
alert.addAction(yesClearAction)
alert.addAction(noClearAction)
presentViewController(alert, animated: true, completion: nil)
}
func clearListNow(entity: String) {
self.rows.removeAllObjects()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return self.rows.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("FruitCell", forIndexPath: indexPath) as? MyCell
cell!.textLabel?.text = self.rows[indexPath.row] as? String
return cell!
}
}
here a screen shot of my storyboard :
As per your current code TableView Reload after AlertView present
so, tableView DataSource (Array) not change and tableview Display datasource(array) data.
try to relod table after
self.clearListNow("GroceryList")
i.e.
self.clearListNow("GroceryList")
self.tableView.reloadData()
or
into func clearListNow(entity: String)
after for loop
i.e.
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
}
self.tableView.reloadData()
so tableview get latest datasource and display it.
Let me know if this works...

Resources