保存到CoreData后重复的值

时间:2019-07-27 15:11:15

标签: ios swift core-data

我目前在我的项目中有2个视图:一个ViewController,带有一个显示事务列表的TableView和一个ViewController,用于创建新事务。

我遇到的问题是,在创建新事务后,它会成功加载到我的TableView上,但是当我强制关闭并重新打开应用程序时,该值是重复的。据我所知,save()函数仅被调用一次,AppDelegate / SceneDelegate中没有任何反应。请参阅GIF以获取正在发生的事的示例。

GIF Demonstrating Issue

这是我的TranasctionsTableViewController:

class TransactionsTableViewController: UIViewController {
    // MARK: - Properties
    var entries: [NSManagedObject] = []
    var container: NSPersistentContainer!

    // MARK: - IBOutlets
    @IBOutlet var tableView: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()

        // setup persistent container
        container = NSPersistentContainer(name: "expenses")
        // load store
        container.loadPersistentStores { storeDescription, error in
            if let error = error {
                print("Unresolved error \(error)")
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        switch segue.identifier! {
        case "NewTransactionSegue":
            // pass an entry to the destination segue
            let destination = segue.destination as! UINavigationController
            let targetController = destination.topViewController as! NewTransactionViewController
            let managedContext = container.viewContext
            let entity = NSEntityDescription.entity(forEntityName: "Entry", in: managedContext)!
            let entry = NSManagedObject(entity: entity, insertInto: managedContext)
            targetController.entry = entry as? Entry
        default:
            print("Unknown segue: \(segue.identifier!)")
        }
    }

    @IBAction func unwindToTransactionList(sender: UIStoryboardSegue) {
        print("unwind segue called!")
        if let sourceViewController = sender.source as? NewTransactionViewController, let entry = sourceViewController.entry {
            print(entry)
            self.save(entryDescription: entry.entryDescription, amount: entry.amount, date: entry.date, id: entry.id)

            // reset the tableView to defaults if no data message was displayed before loading data.
            if self.tableView.backgroundView != nil {
                self.tableView.backgroundView = nil
                self.tableView.separatorStyle = .singleLine
            }

            self.tableView.reloadData()
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // load managedCOntext
        let managedContext = container.viewContext

        // try to fetch data from CoreData. If successful, load into entries.
        do {
            entries = try managedContext.fetch(Entry.fetchRequest())
        } catch let error as NSError {
            print("Could not fetch. \(error), \(error.userInfo)")
        }
    }

    // save a new entry to the data store
    func save(entryDescription: String, amount: Double, date: Date, id: UUID) {
        print("save called!!")
        let managedContext = container.viewContext

        let entity = NSEntityDescription.entity(forEntityName: "Entry", in: managedContext)!

        let entry = NSManagedObject(entity: entity, insertInto: managedContext)

        entry.setValue(entryDescription, forKey: "entryDescription")
        entry.setValue(amount, forKey: "amount")
        entry.setValue(date, forKey: "date")
        entry.setValue(id, forKey: "id")

        do {
            try managedContext.save()
            entries.append(entry)
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
    }

    // save the current container context
    func saveContext() {
        if container.viewContext.hasChanges {
            do {
                try container.viewContext.save()
            } catch {
                print("An error occurred while saving: \(error)")
            }
        }
    }
}

这是我的NewTransactionViewController:

class NewTransactionViewController: UIViewController, UITextFieldDelegate {
    /*
     This value is either passed by `TransactionTableViewController` in `prepare(for:sender:)`
     or constructed as part of adding a new transaction.
     */
    var entry: Entry?

    // MARK: - IBOutlets
    @IBOutlet weak var transactionDescriptionLabel: UILabel!
    @IBOutlet var transactionDescriptionTextField: UITextField!
    @IBOutlet var transactionAmountLabel: UILabel!
    @IBOutlet var transactionAmountTextField: UITextField!
    @IBOutlet weak var cancelButton: UIBarButtonItem!
    @IBOutlet weak var saveButton: UIBarButtonItem!

    // MARK: Constants
    let TRANSACTION_DESCRIPTION_TEXT_FIELD_TAG = 0
    let TRANSACTION_AMOUNT_TEXT_FIELD_TAG = 1


    override func viewDidLoad() {
        super.viewDidLoad()

        // Handle textfield input through delegate callbacks.
        transactionDescriptionTextField.delegate = self
        transactionAmountTextField.delegate = self

        // Adds done button to keypad
        transactionAmountTextField.addDoneButtonToKeyboard(myAction: #selector(self.transactionAmountTextField.resignFirstResponder))
    }

    // MARK: - UITextFieldDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // If the First Responder is the Description Text Field, transfer First Responder to Amount Text Field
        if (textField.tag == TRANSACTION_DESCRIPTION_TEXT_FIELD_TAG) {
            transactionAmountTextField.becomeFirstResponder()
        }
        textField.resignFirstResponder()
        return true
    }

    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: segue)

        // Configure the destination view controller only when the save button is pressed.
        guard let button = sender as? UIBarButtonItem, button === saveButton else {
            os_log("The save button was not pressed, cancelling", log: OSLog.default, type: .debug)
            return
        }

        let transactionDescription = transactionDescriptionTextField.text ?? ""
        let transactionAmount = Double(transactionAmountTextField.text!) ?? 0.00

        // Set the entry to be passed to TransactionTableViewController after the unwind segue.
        entry?.setValue(transactionDescription, forKey: "entryDescription")
        entry?.setValue(transactionAmount, forKey: "amount")
        entry?.setValue(UUID(), forKey: "id")
        entry?.setValue(Date(), forKey: "date")
    }

    // MARK: - IBActions
    @IBAction func cancelButtonTapped(sender: UIBarButtonItem) {
    }

    @IBAction func saveButtonTapped(sender: UIBarButtonItem) {
    }
}

0 个答案:

没有答案