DJ-Glock
DJ-Glock

Reputation: 1411

CoreData update of the row cause insert of blank row

I'm learning how to work with CoreData and faced the issue below.

I have created this function that should update existing row or insert new one. But when I'm trying to update existing one, app inserts blank row.

Here is my part of code:

func saveSettingToDatabase()
{
    guard settingNameLabel.text != nil else {return}

    let context = AppDelegate.viewContext
    let tableContext = SettingsTable(context: context)

    // Get record if already exists
    let request: NSFetchRequest<SettingsTable> = SettingsTable.fetchRequest()
    let searchString = settingNameLabel.text!
    request.predicate = NSPredicate(format: "settingName = %@", searchString)
    let fetchResult = try? context.fetch(request)

    //If record exists, update it. Else - insert.
    if fetchResult?.count == 1 {
        let change = fetchResult?[0]
        change?.setValue(settingNameLabel.text, forKey: "settingName")
        change?.setValue(settingValueLabel.text, forKey: "settingValue")
        change?.setValue(booleanValueSwich.isOn, forKey: "booleanValue")
        try? context.save()
    } else
    {
        tableContext.settingName = settingNameLabel.text
        tableContext.settingValue = settingValueLabel.text
        tableContext.booleanValue = booleanValueSwich.isOn
        context.insert(tableContext)
        try? context.save()
    }
}

Step by step:

  1. Open App.

  2. Fill settingNameLabel with test1.

  3. Click get button.

  4. Values appeared in respective textfields. Here is screenshot of the database before update:

before update

  1. Change the value in settingValueLabel.text to test999.

  2. Click Save.

  3. As per below screenshot - value was changed, but app added blank line (1st line).

after update

I have put breakpoint here:

context.insert(tableContext)

but my program never goes here. And there is no other inserts that could be done in my class.

Can somebody advise please?

Upvotes: 1

Views: 555

Answers (1)

DJ-Glock
DJ-Glock

Reputation: 1411

I have found this suggestion very helpful: Swift Core Data adding extra empty row So I have implemented awakeFromInsert function in my SettingsTable class. After debugging I can see that insert is initianed here:

let tableContext = SettingsTable(context: context)

I have moved this line into else statement and it works properly now.

func saveSettingToDatabase()
{
    guard settingNameLabel.text != nil else {return}

    let context = AppDelegate.viewContext

    // Get record if already exists
    let request: NSFetchRequest<SettingsTable> = SettingsTable.fetchRequest()
    let searchString = settingNameLabel.text!
    request.predicate = NSPredicate(format: "settingName = %@", searchString)
    let fetchResult = try? context.fetch(request)

    //If record exists, update it. Else - insert.
    if fetchResult?.count == 1 {
        let change = fetchResult?[0]
        change?.setValue(settingNameLabel.text, forKey: "settingName")
        change?.setValue(settingValueLabel.text, forKey: "settingValue")
        change?.setValue(booleanValueSwich.isOn, forKey: "booleanValue")
        try? context.save()
    } else
    {
        let tableContext = SettingsTable(context: context)
        tableContext.settingName = settingNameLabel.text
        tableContext.settingValue = settingValueLabel.text
        tableContext.booleanValue = booleanValueSwich.isOn
        context.insert(tableContext)
        try? context.save()
    }
}

And after some refactoring this func looks much more clear:

func saveSettingToDatabase()
{
    let context = AppDelegate.viewContext
    // Get record if already exists
    let request: NSFetchRequest<SettingsTable> = SettingsTable.fetchRequest()
    request.predicate = NSPredicate(format: "settingName = %@", settingNameTextField.text!)
    let fetchResult = try? context.fetch(request)

    //If record exists, update it. Else - insert.
    if fetchResult?.count == 1 {
        let change = fetchResult?[0]
        change?.settingName = settingNameTextField.text
        change?.settingValue = settingValueTextField.text
        change?.settingBooleanValue = settingBooleanValueSwitch.isOn
        try? context.save()
    } else
    {
        let addRecord = SettingsTable(context: context)
        addRecord.settingName = settingNameTextField.text
        addRecord.settingValue = settingValueTextField.text
        addRecord.settingBooleanValue = settingBooleanValueSwitch.isOn
        context.insert(addRecord)
        try? context.save()
    }
}

Upvotes: 1

Related Questions