每次我显示视图控制器时,CoreData 都会再次添加到表视图中(重复数据)
Posted
技术标签:
【中文标题】每次我显示视图控制器时,CoreData 都会再次添加到表视图中(重复数据)【英文标题】:CoreData gets added to Table View AGAIN Every Time I Show View Controller (duplicates data) 【发布时间】:2021-05-31 23:36:56 【问题描述】:我按照这个教程 https://www.youtube.com/watch?v=35mKM4IkHS8&lc=UgztyK4XjUuAOrKk0XJ4AaABAg.9LtwRc_M0Gv9Nt8GIlAzDo
基本上我做了一个具有核心数据保存功能的记事本应用程序。 我在另一个视图控制器上制作了这个应用程序 所以有 MainViewController > NoteViewViewController 我第一次单击记事本部分时,它可以很好地加载核心数据,但是如果我关闭 NoteView 并重新打开它 - 它会复制核心数据中所有保存的笔记 这里是。注意视图控制器
import UIKit
import CoreData
var noteList = [Note]()
class NoteTableView: UITableViewController
func nonDeletedNotes() -> [Note]
var noDeleteNoteList = [Note]()
for note in noteList
if(note.deletedDate == nil)
noDeleteNoteList.append(note)
return noDeleteNoteList
var firstLoad = true
override func viewDidLoad()
if(firstLoad == true)
firstLoad = false
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Note")
do
let results:NSArray = try context.fetch(request) as NSArray
for result in results
let note = result as! Note
noteList.append(note)
catch
print("Fetch Failed")
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell
let noteCell = tableView.dequeueReusableCell(withIdentifier: "noteCellID", for: indexPath) as! NoteCell
let thisNote: Note!
thisNote = nonDeletedNotes()[indexPath.row]
noteCell.titleLabel.text = thisNote.title
noteCell.descLabel.text = thisNote.desc1
return noteCell
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return nonDeletedNotes().count
override func viewDidAppear(_ animated: Bool)
tableView.reloadData()
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
self.performSegue(withIdentifier: "editNote", sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if(segue.identifier == "editNote")
let indexPath = tableView.indexPathForSelectedRow!
let noteDetail = segue.destination as? FocusWheelViewController
let selectedNote : Note!
selectedNote = nonDeletedNotes()[indexPath.row]
noteDetail!.selectedNote = selectedNote
tableView.deselectRow(at: indexPath, animated: true)
我确定有一个通用的解决方案,但我不确定它是什么,也无法关注提出类似问题的帖子,因为我的代码不同,而且我确实不太了解机制对此应用其他答案
【问题讨论】:
【参考方案1】:我发现最简单的解决方案是添加这两行,以便每次刷新表格视图,然后加载数据
noteList.removeAll()
tableView.reloadData()
所以代码看起来像这样:
var firstLoad = true
override func viewDidLoad()
if(firstLoad == true)
noteList.removeAll() //NEWCODE
tableView.reloadData() //NEWCODE
firstLoad = false
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Note")
do
let results:NSArray = try context.fetch(request) as NSArray
for result in results
let note = result as! Note
noteList.append(note)
catch
print("Fetch Failed")
【讨论】:
【参考方案2】:问题是var firstLoad = true
。因为每次控制器启动时,firtLoad 始终为 true,应用程序将从 Coredata 获取数据并附加到 noteList。
解决方案是 UserDefaults。第一次运行应用程序时,firstLoad 始终为 true。所以需要将firstLoad的值bool保存到UserDefaults
// Set
UserDefaults.standard.setValue(true, forKey: "firstLoad")
// Get
UserDefaults.standard.bool(forKey: "firstLoad")
import UIKit
import CoreData
class NoteTableView: UITableViewController
var noteList = [Note]()
func nonDeletedNotes() -> [Note]
var noDeleteNoteList = [Note]()
for note in noteList
if(note.deletedDate == nil)
noDeleteNoteList.append(note)
return noDeleteNoteList
override func viewDidLoad()
if noteList.count == 0
if(UserDefaults.standard.bool(forKey: "firstLoad") == true)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Note")
do
let results:NSArray = try context.fetch(request) as NSArray
for result in results
let note = result as! Note
noteList.append(note)
UserDefaults.standard.setValue(false, forKey: "firstLoad")
catch
print("Fetch Failed")
else
UserDefaults.standard.setValue(false, forKey: "firstLoad")
也许你在从 CoreData 获取数据时需要检查重复值。
【讨论】:
非常感谢您的回答,它解决了重复问题,但在应用程序关闭并重新打开后似乎没有保留数据。可能是我的菜鸟错误,但你怎么看? 我认为当你停止应用程序时,一切都会被中止以释放内存。然后,当您再次启动时,应用程序将存储来自 CoreData 的数据。这是必要的,一旦应用关闭,您将无法保留数据。 嗯,对于旧代码,它完美地存储了数据。如果我关闭并重新打开应用程序,我所有的笔记都还在。我不确定发生了什么变化 那么,你可以用viewWillAppear
替换viewDidLoad
吗?因为viewWillAppear
会在您激活控制器时调用。
这真的很有帮助,它也停止了复制,但它也阻止它在应用程序关闭并重新打开后加载保存的笔记,就像在 kiete 的帮助下一样。这真的很有趣,我还不确定为什么会发生这种情况以上是关于每次我显示视图控制器时,CoreData 都会再次添加到表视图中(重复数据)的主要内容,如果未能解决你的问题,请参考以下文章
线程化核心数据和 UINavigationController
每次推送新路线时,都会再次显示最后的 Flutter SnackBar