如何在swift中删除行后刷新tableview?

Posted

技术标签:

【中文标题】如何在swift中删除行后刷新tableview?【英文标题】:How to refresh tableview after deleting row in swift? 【发布时间】:2016-07-17 16:54:37 【问题描述】:

我有三个视图控制器。

VC1 和 VC3 是 UITableViewControllers 的子类,VC2 是 UIViewController 的子类。

VC1 将一些数据传递给 VC2。 VC2 使用 userdefaults 将数据保存到数组中。然后 VC2 使用 segue 将此数据传递给 VC3。 VC3 在表格视图中显示数据。

我添加了一个滑动手势来从 VC3 的表格视图中删除数据。而且效果很好。但是当我返回 (VC3 -> VC2) 并再次返回 (VC2 -> VC3) 时,删除的行仍然存在数据。但是当我转到 VC3 -> VC2 -> VC1 并再次返回 VC1 -> VC2 -> VC3 时,我发现已删除的行实际上已删除。我希望当 VC3 > VC2 然后 VC2 > VC3 时不存在已删除的数据。

所有视图控制器都在 UINavigationController 堆栈中。代码是用 Swift 2 编写的。

【问题讨论】:

【参考方案1】:

为什么不为所有视图和相应的表编写一个函数。

好像

导入基础 导入 UIKit

class DeleteRows
    class func removeRowAtIndexPath(indexPathRow: Int, indexPathSec: Int, table: UITableView) -> UITableView
arrayOfSomethin.removeAtIndex(indexPathRow)
    let index = NSIndexPath(forItem: indexPathRow, inSection: indexPathSec)
    table.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Left)

    return table


您可以通过 DeleteRows.removeRowAtIndexPath(indexPathRow: 0, indexPathSec: 0,table:Yourtable).delegate = self 调用它们

【讨论】:

【参考方案2】:

删除后需要更新数据。

在 viewDidLoad() 或 delete 方法的末尾,添加:

tableview.reloadData()

这应该有助于更新视图。

要存储/保留数据,请使用 UserDefaults。

func storeData(name: String) 

    let defaults = UserDefaults.standard
    defaults.set(name, forKey: "Name")
    defaults.synchronize() // Save Data



func getData() -> String 

    if let name = UserDefaults.standard.object(forKey: "Name") 
        return name as! String
     else 
        return "" // error in retrieving data (ex: name not found)
    


【讨论】:

【参考方案3】:

最佳解决方案 您的解决方案之一可能是使用通知模式。

从您的 VC3 类发送通知:

NSNotificationCenter.defaultCenter().postNotificationName("ObjectDeleted", object: ["object" : object])

在您的 VC1 和 VC2 中,您必须订阅删除事件(在 viewDidLoad() 的某处)

NSNotificationCenter.defaultCenter().addObserver(self,
                                                 selector: #selector(VC1.objectDeleted(_:)),
                                                 name: "ObjectDeleted",
                                                 object: nil)

你可以像这样处理它:

func objectDeleted(notification: NSNotification) 

    guard let object = userInfo["object"] as? YourObjectClass else  return 
    guard let index = dataArray.indexOf(object) else  return 

    dataArray.removeAtIndex(index)
    tableView.deleteRowsAtIndexPaths([NSIndexPath.init(forRow: index, inSection: 0)], withRowAnimation: .Automatic)

对于 VC2,您也可以在上面的函数中更新您的 NSUserDefaults 容器。

使用 ios 8 或更早版本,您需要在解除分配观察者对象(在您的情况下为 VC1 或 VC2)之前取消注册此通知。如果您忘记了,当通知中心将下一个通知发送到不再存在的对象时,您将面临崩溃的风险。所以不要忘记添加一个 deinit 调用

deinit 
   NSNotificationCenter.defaultCenter().removeObserver(self)

【讨论】:

不,这不是最好的方法。由于 VC 使用委托关联,因此关闭回调或展开是更好的技术。 @vikingosegundo 我宁愿保持代码松耦合。您的方法也很好,但直到您想在您的应用程序中进行一些架构更改。或者在另一个地方对删除做出反应,因为它通常会发生 @vikingosegundo 顺便说一句,我看不出任何 VC 都通过任何协议相互关联 你的代码并没有糟糕的耦合——相反:它对 NSNotificationCenter 有一个隐藏的依赖。 VC 在相互创造时相互关联。 @vikingosegundo “糟糕的耦合”?我喜欢它。【参考方案4】:

您需要从数据源中删除数据并使用 tableview.reloadData() 更新 tableview

编辑!!

当您导航回 VC2(VC3-> VC2) 时,您应该引用您删除的数据,以便可以从 dataSource(array, nsuserdefaults) 中删除它。 这样,当您想从 VC2 -> VC3 导航时,您将从 NSUserDefaults 带来一个新数组,然后使用该新数据重新加载 tableview。

但我建议您将其简化。好像是在给自己找麻烦。如果您想使用来自多个视图控制器的数据访问一个数组,您应该使用一个包含该数组的类创建一个新文件。看看这个 sudo 代码:

"dataSource.swift"


Class DataSource
    var arrayWithData = [String]()


    init()
         let userDefault = NSUserDefaults.standardUserDefaults()
         self.arrayWithData = userDefaults.arrayForKey("arrayData")
    

     func deleteData()
         //Edit the self.arrayWithData and then run this method
         let userDefault = NSUserDefaults.standardUserDefaults()
         userDefault.updateValue(self.arrayWithData, forKey "arrayData")
      


【讨论】:

问题是如何在 3 个视图控制器之间保持数据一致 reloadData() 完全清除表并重新加载数据。因此,如果您向下滚动表格并调用此方法,则会重置滚动位置 我已经将 tableview.reloadData 添加到 VC3 的 viewDidLoad 和 viewWillAppear 中。但是它不起作用。 @Alex 它不应该 - 因为即使您在 VC3 中更新数据容器,当您执行 VC3->VC2->VC3 转换时,它也会被从 VC2 传递的旧数据容器覆盖 @slxl 你是对的。但我无法理解你的代码。请您解释或简化您的代码。【参考方案5】:

首先要从填充 tableView 的数据源中删除数据。很可能您有一些类/结构类型的数组,例如 let usersArray = [Users]() 然后您需要从 tableView 中删除该行。 笔记!!!如果您使用 reload tableView.reloadRows(at: [indexPath], with: .automatic) 应用程序将崩溃。这种方法就像您插入一行一样,但您的数据源告诉该特定索引没有数据,因此您应该使用table.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Left)

//remove users from dataSource
  usersArray.remove(at:indexPath.row)
 //delete the row of the tableView
  table.deleteRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Left)

【讨论】:

以上是关于如何在swift中删除行后刷新tableview?的主要内容,如果未能解决你的问题,请参考以下文章

C# - 删除行后如何刷新 DataGridView

如何在单元格 Swift 2 中删除项目后重新加载表格视图

Swift:如何无延迟地刷新 tableview (UIRefreshControl)

Swift 3:TableView 刷新不适用于行操作

删除数据库行后刷新自定义游标适配器

如何在单击 tabBar 项目 Swift 上刷新 tableView?