You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Navigation Controller在视图间传递并操作Core Data对象

解决纯代码导航下Core Data对象在视图控制器间的传递与修改问题

问题背景

我需要在UITableView的didSelectRowAt方法中把Core Data对象传递给另一个视图控制器,目前能通过navigationController?.pushViewController实现页面跳转,但不清楚不使用Storyboard、纯代码加载视图的场景下如何传值,同时要在第二个控制器中访问并修改这个Core Data对象。现有代码如下:


第一个视图控制器(含UITableView)

var items = [Item]() // Core Data实体数组

...
override func viewWillAppear(_ animated: Bool) {
    items = DBManager.share.fetchItems()
    homeTableView.reloadData()
}

extension FirstVC : UITableViewDelegate, UITableViewDataSource {
...
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "homeCell", for: indexPath) as? HomeTableCell else { return UITableViewCell() }
        
        let newItem = items[indexPath.row]
        cell.homeCellTitle.text = newItem.title
        cell.homeCellPrice.text = newItem.price
        cell.homeCellPost?.text = newItem.post
        
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedItem = self.items[indexPath.row]

        guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondVC") as? SecondVC else {return}
        self.navigationController?.pushViewController(vc, animated: true)
        
    }
}

第二个视图控制器

class SecondVC: UIViewController {
    var selectedItem: Item?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func editButtonPressed(_ sender: Any) {
       // 不知道如何修改Core Data对象
    }
}

DBManager(Core Data管理类)

import UIKit
import CoreData

class DBManager{
    static let share = DBManager()
    
    // MARK: - Core Data stack
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "RC_week3")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support
    lazy var context = persistentContainer.viewContext
    func saveContext () {
        if context.hasChanges {
            do{
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
    
    func fetchItems() -> [Item]
    {
        var Items = [Item]()
        
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: Item.description())
        
        do{
            Items = try context.fetch(fetchRequest) as! [Item]
        }catch{
            print("fetching error")
        }
        return Items
    }
    
}

解决方案

1. 纯代码初始化第二个VC并传递Core Data对象

修改第一个VC的didSelectRowAt方法,直接通过代码初始化SecondVC,并给其selectedItem属性赋值(Core Data对象是引用类型,传递后两个VC操作的是同一个实例):

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selectedItem = self.items[indexPath.row]
    // 纯代码初始化第二个VC,替代Storyboard实例化方式
    let vc = SecondVC()
    // 传递选中的Core Data对象
    vc.selectedItem = selectedItem
    self.navigationController?.pushViewController(vc, animated: true)
}

2. 在第二个VC中修改Core Data对象并保存

在editButtonPressed方法中直接修改selectedItem的属性,调用DBManager的saveContext()方法即可将修改同步到数据库:

class SecondVC: UIViewController {
    var selectedItem: Item?

    override func viewDidLoad() {
        super.viewDidLoad()
        // 可选:在这里将selectedItem的现有数据展示到UI组件(如文本框)
    }

    @IBAction func editButtonPressed(_ sender: Any) {
        guard let item = selectedItem else { return }
        
        // 修改Core Data对象的属性
        item.title = "更新后的标题"
        item.price = "更新后的价格"
        item.post = "更新后的内容"
        
        // 保存上下文,同步修改到数据库
        DBManager.share.saveContext()
        
        // 保存完成后返回上一页
        navigationController?.popViewController(animated: true)
    }
}

3. 返回第一个VC后刷新数据

第一个VC的viewWillAppear方法已经实现了重新获取数据并刷新表格,保留即可确保返回后能看到修改后的内容:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    items = DBManager.share.fetchItems()
    homeTableView.reloadData()
}

额外提示

  • Core Data对象是引用类型,传递后无需通过ID重新查询,直接修改即可
  • 如果需要更健壮的错误处理,可以修改DBManager的saveContext()方法,替换fatalError为打印错误或弹出提示
  • 确保Item实体的属性类型与修改时赋值的类型一致(如title为String类型)

内容的提问来源于stack exchange,提问作者plzhelpme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:16:11