如何在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?的主要内容,如果未能解决你的问题,请参考以下文章