0
votes

I'm pretty new to iOS dev/Core Data and am having trouble implementing one part of my workflow within my app. See below:

TableView workflow

Core Data Properties:

  • item
  • Attributes: title, amount, date, status, category (rel), note (rel)

  • note

  • Attributes: title, contents, createdAt, updatedAt, item (rel)

When a user creates a new item, all attributes are required, except for .note as I'd like to give the user the option to create a note at a later time if only needed.

What I want to accomplish:

  1. User selects row to display item details
  2. On item details view, user selects notes (highlighted in yellow above) to go to Add/Edit notes
  3. The note is just a single object that the user can enter/update the note. So basically, one note per item.

MY CODE

Xcode 11.5, Swift 5

import UIKit
import CoreData

class NoteVC: UIViewController, UITextFieldDelegate, UITextViewDelegate {

//MARK: - Core Data

var item: Item?
var context: NSManagedObjectContext!


//MARK: - Outlets

@IBOutlet weak var headerContainer: UIView!
@IBOutlet weak var headerTitle: UILabel!
@IBOutlet weak var noteView: UIView!
@IBOutlet weak var noteTitleTextField: UITextField!
@IBOutlet weak var noteContentTextView: UITextView!
@IBOutlet weak var noteDataLabel: UILabel!



override func viewDidLoad() {
    super.viewDidLoad()

    setupView()


}

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

    //Update note
    if let title = noteTitleTextField.text, !title.isEmpty {
        item?.notes?.title = title
        item?.notes?.contents = noteContentTextView.text
    }

    item?.notes?.updatedAt = Date()
    item?.notes?.contents = noteContentTextView.text


}
    private func setupView() {

    noteTitleTextField.text = item?.notes?.title
    noteContentTextView.text = item?.notes?.contents
    noteDataLabel.text = DateHelper.convertDate(date: Date())

}

//MARK: - Actions

@IBAction func doneButtonTapped(_ sender: UIButton) {


    item?.notes?.title = noteTitleTextField.text
    item?.notes?.contents = noteContentTextView.text
    item?.notes?.createdAt = Date()
    dismiss(animated: true)



}


}

MY PROBLEM

I'm having an issue creating the new note and assign it to that item and therefore populating the note details for editing. I was able to set the attributes for item.date, .category successfully to another modal view controller (so the passing of data is working), but to no avail with the Notes. Not sure if its because of the relationship or not. Again, I'm a n00b to Core Data so please forgive me for sounding simple.

Any help is appreciated.

Asking for a friend, =P

adrapp

1

1 Answers

0
votes

Your problem seems to be that you are not creating a Note entity before trying to assign its properties.

The correct pattern to create a note and associate it with your item would be something like this:

if let note = NSEntityDescription.insertNewObject(forEntityName: "note", into: context) as? Note {

    //set note properties
    note.title = noteTitleTextField.text
    note.contents = noteContentTextView.text
    note.createdAt = Date()

    //set relationship to item
    item.note = note
}

Please verify the name of the entity ("note") and class ("Note") match what you defined in your project.

To allow updating an existing note, you need to check first if there is an existing note. You could modify the code above as follows:

// get the existing note, if any, or create a new one
let note = item.note ?? NSEntityDescription.insertNewObject(forEntityName: "note", into: context) as? Note

// if note existed or was successfully created...
if let note = note {
    //set note properties
    note.title = noteTitleTextField.text
    note.contents = noteContentTextView.text

    if item.note == nil {
        note.createdAt = Date()
    }
    else {
        note.updatedAt = Date()
    }

    //set relationship to item
    item.note = note
}