如何将第二个表格视图的值与第一个表格视图的单击行的关系分开?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将第二个表格视图的值与第一个表格视图的单击行的关系分开?相关的知识,希望对你有一定的参考价值。

我是Swift的新手,需要您的帮助。

在我的应用中,我有两个视图控制器。两者都具有动态表视图。第一个视图控制器及其表显示了一些类别(称为组),第二个视图控制器显示了属于这些类别的一些对象(称为单个组)。用户可以在两个表视图中添加和删除所有内容。我将每个表视图的值保存在数组中,并在核心数据中使用两个实体(每个表视图一个实体)。在核心数据中,我将类别/对象的ID保存为UUID,将标题保存为字符串。另外,每个UUID都有一个索引,因此每个值都有其自己的位置。

现在是我的问题:

当我单击第一个表视图中的一行时,将显示下一个视图控制器(detailViewController)。我可以添加一些东西,一切正常。但是,当我返回并在第一个表格视图中单击另一行时,它再次在detailViewController上显示了相同的内容。

所以我认为我必须将第二个表格视图中的对象与第一个表格视图中的每一行分开。但是我不知道该怎么做。

我想到的是从secondViewController中保存与第一个表视图中的行值的索引有关的数组。困难是我将应用程序中的所有内容分离到了不同的文件中。因此,Core Data拥有自己的文件以及具有数组和视图控制器本身的存储。

App Structure

因此,我不知道您到底需要什么代码。我希望这足够了:

班级组

import Foundation

class Group {
    private(set) var groupId    : UUID
    private(set) var groupTitle : String

    init(groupTitle: String) {
        self.groupId    = UUID()
        self.groupTitle = groupTitle
    }

    init(groupId: UUID, groupTitle: String) {
        self.groupId    = groupId
        self.groupTitle = groupTitle
    }
}

Class SingleGroup

import Foundation

class SingleGroup {
    private(set) var singleGroupId          : UUID
    private(set) var singleGroupName        : String
    private(set) var singleGroupAmount      : Double
    private(set) var singleGroupTimeStamp   : Int64


    init(singleGroupName: String, singleGroupAmount: Double, singleGroupTimeStamp: Int64) {
        self.singleGroupId          = UUID()
        self.singleGroupName        = singleGroupName
        self.singleGroupAmount      = singleGroupAmount
        self.singleGroupTimeStamp   = singleGroupTimeStamp
    }

    init(singleGroupId: UUID, singleGroupName: String, singleGroupAmount: Double, singleGroupTimeStamp: Int64) {
        self.singleGroupId          = singleGroupId
        self.singleGroupName        = singleGroupName
        self.singleGroupAmount      = singleGroupAmount
        self.singleGroupTimeStamp   = singleGroupTimeStamp
    }
}

存储组

import CoreData

class Storage {
    static let storage : Storage = Storage()

    private var groupIndexToIdDict : [Int:UUID] = [:]
    private var currentIndex : Int = 0

    private(set) var managedObjectContext : NSManagedObjectContext
    private var managedContextHasBeenSet: Bool = false

    //need to init the ManageObjectContext, it will be overwritten when setManagedContext is called from the view controller
    init() {
        managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
    }


    func setManagedContext(managedObjectContext: NSManagedObjectContext) {
        self.managedObjectContext = managedObjectContext
        self.managedContextHasBeenSet = true
        let groups = CoreDataHelper.readGroupsFromCoreData(fromManagedObjectContext: self.managedObjectContext)
        currentIndex = CoreDataHelper.count
        for (index, group) in groups.enumerated() {
            groupIndexToIdDict[index] = group.groupId
        }
    }


    func addGroup(groupToBeAdded: Group) {
        if managedContextHasBeenSet {
            // add group UUID to the dictionary
            groupIndexToIdDict[currentIndex] = groupToBeAdded.groupId
            // call Core Data Helper to create the new group
            CoreDataHelper.createGroupInCoreData(groupToBeCreated: groupToBeAdded, intoManagedObjectContext: self.managedObjectContext)
            // increase index
            currentIndex += 1
        }
    }

存储单组

import CoreData

class SingleGroupStorage {
    static let singleGroupStorage : SingleGroupStorage = SingleGroupStorage()

    private var singleGroupIndexToIdDict : [Int:UUID] = [:]
    private var currentIndex: Int = 0

    private(set) var managedObjectContext : NSManagedObjectContext
    private var managedContextHasBeenSet: Bool = false

    // need to init the ManagedObjectCOntext, it will be overwritten when setManagedContext is called from the view controller
    init() {
        managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
    }

    func setManagedContext(managedObjectContext: NSManagedObjectContext) {
        self.managedObjectContext = managedObjectContext
        self.managedContextHasBeenSet = true
        let singleGroups = SingleGroupsCoreDataHelper.readSingleGroupsFromCoreData(fromManagedObjectContext: self.managedObjectContext)
        currentIndex = SingleGroupsCoreDataHelper.countSingleGroup
        for (index, singleGroup) in singleGroups.enumerated() {
            singleGroupIndexToIdDict[index] = singleGroup.singleGroupId
        }
    }

    func addSingleGroup(singleGroupToBeAdded: SingleGroup) {
        if managedContextHasBeenSet {
            // add singlegroup UUID to the dictionary
            singleGroupIndexToIdDict[currentIndex] = singleGroupToBeAdded.singleGroupId
            // call Core Data Helper to create the new single group
            SingleGroupsCoreDataHelper.createSingleGroupInCoreData(singleGroupToBeCreated: singleGroupToBeAdded, intoManagedObjectContext: self.managedObjectContext)
            // increase index
            currentIndex += 1
        }
    }

核心数据助手组

import Foundation
import CoreData

class CoreDataHelper {

    private(set) static var count : Int = 0

    static func createGroupInCoreData(groupToBeCreated: Group, intoManagedObjectContext: NSManagedObjectContext) {

        // create an entity and new group record
        let groupEntity = NSEntityDescription.entity(forEntityName: "Groups", in: intoManagedObjectContext)!

        let newGroupToBeCreated = NSManagedObject(entity: groupEntity, insertInto: intoManagedObjectContext)
        newGroupToBeCreated.setValue(groupToBeCreated.groupId, forKey: "groupId")
        newGroupToBeCreated.setValue(groupToBeCreated.groupTitle, forKey: "groupTitle")

        do {
            try intoManagedObjectContext.save()
            count += 1
        } catch let error as NSError {
            print("Could not save group. (error), (error.userInfo)")
        }
    }


    static func readGroupFromCoreData(groupIdToBeRead: UUID, fromManagedObjectContext: NSManagedObjectContext) -> Group? {

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Groups")

        let groupIdPredicate = NSPredicate(format: "groupId = %@", groupIdToBeRead as CVarArg)
        fetchRequest.predicate = groupIdPredicate

        do {
            let fetchedGroupsFromCoreData = try fromManagedObjectContext.fetch(fetchRequest)
            let groupManagedObjectToBeRead = fetchedGroupsFromCoreData[0] as! NSManagedObject
            return Group.init(
                groupId: groupManagedObjectToBeRead.value(forKey: "groupId") as! UUID,
                groupTitle: groupManagedObjectToBeRead.value(forKey: "groupTitle") as! String)

        } catch let error as NSError {
            // TODO error handling
            print("Could not read group. (error), (error.userInfo)")
            return nil
        }
    }

核心数据助手单个组

import Foundation
import CoreData

class SingleGroupsCoreDataHelper {

    private(set) static var countSingleGroup : Int = 0

    static func createSingleGroupInCoreData(singleGroupToBeCreated: SingleGroup, intoManagedObjectContext: NSManagedObjectContext) {

        // create an entity and new single group record
        let singleGroupEntity = NSEntityDescription.entity(forEntityName: "SingleGroups", in: intoManagedObjectContext)!

        let newSingleGroupToBeCreated = NSManagedObject(entity: singleGroupEntity, insertInto: intoManagedObjectContext)
        newSingleGroupToBeCreated.setValue(singleGroupToBeCreated.singleGroupId, forKey: "singleGroupId")
        newSingleGroupToBeCreated.setValue(singleGroupToBeCreated.singleGroupName, forKey: "singleGroupName")
        newSingleGroupToBeCreated.setValue(singleGroupToBeCreated.singleGroupAmount, forKey: "singleGroupAmount")
        newSingleGroupToBeCreated.setValue(singleGroupToBeCreated.singleGroupTimeStamp, forKey: "singleGroupTimeStamp")

        do {
            try intoManagedObjectContext.save()
            countSingleGroup += 1
        } catch let error as NSError {
            print("Could not save group. (error), (error.userInfo)")
        }
    }


    static func readSingleGroupFromCoreData(singleGroupIdToBeRead: UUID, fromManagedObjectContext: NSManagedObjectContext) -> SingleGroup? {

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "SingleGroups")

        let singleGroupIdPredicate = NSPredicate(format: "singleGroupId = %@", singleGroupIdToBeRead as CVarArg)
        fetchRequest.predicate = singleGroupIdPredicate

        do {
            let fetchedSingleGroupsFromCoreData = try fromManagedObjectContext.fetch(fetchRequest)
            let singleGroupManagedObjectToBeRead = fetchedSingleGroupsFromCoreData[0] as! NSManagedObject
            return SingleGroup.init(
                singleGroupId: singleGroupManagedObjectToBeRead.value(forKey: "singleGroupId") as! UUID,
                singleGroupName: singleGroupManagedObjectToBeRead.value(forKey: "singleGroupName") as! String,
                singleGroupAmount: singleGroupManagedObjectToBeRead.value(forKey: "singleGroupAmount") as! Double,
                singleGroupTimeStamp: singleGroupManagedObjectToBeRead.value(forKey: "singleGroupTimeStamp") as! Int64)

        } catch let error as NSError {
            // TODO error handling
            print("Could not read single group. (error), (error.userInfo)")
            return nil
        }
    }

第一张表视图

    override func numberOfSections(in tableView: UITableView) -> Int {
    //    return fetchedResultsController.sections?.count ?? 0
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // return objects.count
        return Storage.storage.count()
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "GroupsTableViewCell", for: indexPath) as! GroupsTableViewCell

        if let object = Storage.storage.readGroup(at: indexPath.row) {
            cell.groupTitleLabel!.text = object.groupTitle
        }
        return cell
    }

Segue到detailViewController

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showDetailSegue" {
            if let indexPath = tableView.indexPathForSelectedRow {
                let navTitle = Storage.storage.readGroup(at: indexPath.row)
                let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
                controller.title = navTitle?.groupTitle
            }
        }
    }

第二张表视图

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //return objects.count
        return SingleGroupStorage.singleGroupStorage.countSingleGroup()
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SingleGroupsTableViewCell", for: indexPath) as! SingleGroupsTableViewCell

        if let object = SingleGroupStorage.singleGroupStorage.readSingleGroup(at: indexPath.row) {
            cell.singleGroupNameLabel!.text = object.singleGroupName
            cell.singleGroupAmountLabel!.text = String(format: "%.2f", object.singleGroupAmount)
            cell.singleGroupDateLabel!.text = DateHelper.convertDate(date: Date.init(seconds: object.singleGroupTimeStamp))
        }
        return cell
    }

我几周以来一直在寻找解决方案,但找不到任何东西。

希望您能理解我的问题,并有任何解决方案或提示来解决。

更新:

组-读取(at:)

    func readGroup(at: Int) -> Group? {
        if managedContextHasBeenSet {
            // check input index
            if at < 0 || at > currentIndex - 1 {
                // TODO error handling
                print("Can not read Groups.")
                return nil
            }
            // get group UUID from dictionary
            let groupUUID = groupIndexToIdDict[at]
            let groupReadFromCoreData: Group?
            groupReadFromCoreData = CoreDataHelper.readGroupFromCoreData(groupIdToBeRead: groupUUID!, fromManagedObjectContext: self.managedObjectContext)
            return groupReadFromCoreData
        }
        return nil
    }

同一组相同

    func readSingleGroup(at: Int) -> SingleGroup? {
        if managedContextHasBeenSet {
            // check input index
            if at < 0 || at > currentIndex - 1 {
                // TODO error handling
                print("Can not read SingleGroups.")
                return nil
            }
            // get single group UUID from dicitionary
            let singleGroupUUID = singleGroupIndexToIdDict[at]
            let singleGroupReadFromCoreData: SingleGroup?
            singleGroupReadFromCoreData = SingleGroupsCoreDataHelper.readSingleGroupFromCoreData(singleGroupIdToBeRead: singleGroupUUID!, fromManagedObjectContext: self.managedObjectContext)
            return singleGroupReadFromCoreData
        }
        return nil
    }
答案

更新:

我已经更新了核心数据关系(一对多),现在可以正常工作!谢谢你的提示。

但是现在我有一个新问题:

在我的Group ViewController(带有第一个表格视图)上,我通过警报添加新值。在更新代码之前,当您添加新值时,tableview将重新加载数据并在tableview中显示新值。由于我更新了代码,因此tableview会重新加载数据,但不显示它。我必须切换视图控制器,然后返回以显示它。

我在代码中的任何地方都尝试了groupTableView.reloadData(),但无法正常工作。希望你能帮助我。

代码(组)MasterViewController:

//
//  MasterViewController.swift
//  OhMyMoney
//
//  Created by Mina Kurah on 14.01.20.
//  Copyright © 2020 MyOrganisation. All rights reserved.
//

import UIKit
import CoreData

class MasterViewController: UITableViewController {

    var groups: [Groups] = []

    @IBOutlet weak var groupsTableView: UITableView!

    var groupsTextField: UITextField?


    override func viewDidLoad() {
        super.viewDidLoad()

        self.groupsTableView.delegate = self
        self.groupsTableView.dataSource = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.

    }

    override func viewWillAppear(_ animated: Bool) {

        // Core date initialization
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            // create alert
            let alert = UIAlertController(
                title: "Could not get app delegate",
                message: "Could not get app delegate, unexpected error occured. Try again later.",
                preferredStyle: .alert)

            // add OK action
            alert.addAction(UIAlertAction(title: "OK", style: .default))

            // show alert
                self.present(alert, animated: true)

            return
        }

        let managedContext = appDelegate.persistentContainer.viewContext

        let fetchRequest: NSFetchRequest<Groups> = Groups.fetchRequest()

        do {
            groups = try managedContext.fetch(fetchRequest)

            groupsTableView.reloadData()

        } catch {
            // TODO: error handling
            print("Could not fetch groups")
        }

        navigationItem.leftBarButtonItem = editButtonItem

        let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject))
        navigationItem.rightBarButtonItem = addButton

    }


    // MARK: - add new Group

    @objc func insertNewObject() {
        let addButtonAlert = UIAlertController(title: "Neue Gruppe", message: "Füge eine neue Gruppe deiner Liste hinzu", preferredStyle: .alert)
        addButtonAlert.addTextField { (UITextField) in
            self.groupsTextField = UITextField
            self.groupsTextField?.placeholder = "Name der Gruppe"
            self.groupsTextField?.clearButtonMode = .whileEditing
        }
        let okAction = UIAlertAction(title: "Hinzufügen", style: .default, handler: addNewGroup)
        let cancelAction = UIAlertAction(title: "Abbrechen", style: .cancel, handler: nil)

        addButtonAlert.addAction(okAction)
        addButtonAlert.addAction(cancelAction)

        self.present(addButtonAlert, animated: true)

    }

    func addNewGroup(_:UIAlertAction) -> Void {
        let group = Groups(groupId: UUID(), groupTitle: groupsTextField!.text ?? "")

        do {
            try group?.managedObjectContext?.save()

            groupsTableView.reloadData()

        } catch {
            print("Could not save group")
        }
    }

    // MARK: - Segue

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        guard let destination = segue.destination as? DetailViewController,
            let selectedRow = self.groupsTableView.indexPathForSelectedRow?.row else {
                return
        }
        destination.group = groups[selectedRow]
        destination.title = groups[selectedRow].groupTitle
    }

    // MARK: - delete Group

    func deleteGroup(at indexPath: IndexPath) {
        let group = groups[indexPath.row]

            guard let managedContext = group.managedObjectContext else {
                return
        }

        managedContext.delete(group)

        do {
            try managedContext.save()

            groups.remove(at: indexPath.row)

            groupsTableView.deleteRows(at: [indexPath], with: .automatic)
        } catch {
            //TODO: error handling
            print("Could not delete Group")

            groupsTableView.reloadRows(at: [indexPath], with: .automatic)
        }
    }

    // MARK: - Table View

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return groups.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = groupsTableView.dequeueReusableCell(withIdentifier: "GroupsTableViewCell", for: indexPath)  as! GroupsTableViewCell
        let object = groups[indexPath.row]

        cell.groupTitleLabel?.text = object.groupTitle

        return cell
    }

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            deleteGroup(at: indexPath)
        }
    }
}

以上是关于如何将第二个表格视图的值与第一个表格视图的单击行的关系分开?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 5. 从第二个表格视图单元格(第二个 indexpath.row )显示数组

第二个视图上的表格视图单元格

如何使用按钮使用两个表格视图

将第一个文件的第一列与第二个文件中的行匹配,然后将第二个文件中匹配行的最后一列插入第一个文件中的新第一列

如何通过数组将数据传递给表格视图?

在数据表或连续表单视图中的表单上,我们如何将第二个组合框中的可能值基于第一个组合框中选择的值?