title: core data relationships in creating a favorite button in swift
body: <p>I need some help creating a favorite button in swift. I have been trying to study how to use core data, and i thought that i had a good handle on it, expect i am struggling to use it to create the favorite button. I have a sample project that has two views, a table view with a few numbers and a view controller that has the button. 
  <a href="https://i.stack.imgur.com/RNjkb.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RNjkb.png" alt="this is what it should look like"></a></p>
  
  <p>this is the core data part of the application
  <a href="https://i.stack.imgur.com/3AEaq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3AEaq.png" alt="core data"></a></p>
  
  <p>after watching a video i was told to take the core data functions that save the data from the appDelegate and put it in a new view, which i call PersistenceService.swift</p>
  
  <pre><code>import Foundation
  import CoreData
  
  class PersistenceService {
  
      private init() {}
  
      static var context: NSManagedObjectContext {
          return persistentContainer.viewContext
      }
  
      static  var persistentContainer: NSPersistentContainer = {
          /*
           The persistent container for the application. This implementation
           creates and returns a container, having loaded the store for the
           application to it. This property is optional since there are legitimate
           error conditions that could cause the creation of the store to fail.
           */
          let container = NSPersistentContainer(name: "otherButton")
          container.loadPersistentStores(completionHandler: { (storeDescription, error) in
              if let error = error as NSError? {
                  // Replace this implementation with code to handle the error appropriately.
                  // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
  
                  /*
                   Typical reasons for an error here include:
                   * The parent directory does not exist, cannot be created, or disallows writing.
                   * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                   * The device is out of space.
                   * The store could not be migrated to the current model version.
                   Check the error message to determine what the actual problem was.
                   */
                  fatalError("Unresolved error \(error), \(error.userInfo)")
              }
          })
          return container
      }()
  
      // MARK: - Core Data Saving support
  
      static func saveContext () {
          let context = persistentContainer.viewContext
          if context.hasChanges {
              do {
                  try context.save()
                  print("SAVED")
              } catch {
                  // Replace this implementation with code to handle the error appropriately.
                  // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                  let nserror = error as NSError
                  fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
              }
          }
      }
  }
  </code></pre>
  
  <p>the first view, the tableview, is simple, i just created a table with three cells that when pressed go to a new view. </p>
  
  <p>idTableView.swift</p>
  
  <pre><code>import UIKit
  import CoreData
  
  class idTableView: UITableViewController {
  
  
      var idNumber = [1, 2, 3]
  
      override func viewDidLoad() {
          super.viewDidLoad()
  
      }
  
      override func didReceiveMemoryWarning() {
          super.didReceiveMemoryWarning()
          // Dispose of any resources that can be recreated.
      }
  
      override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          self.performSegue(withIdentifier: "segue", sender: indexPath)
      }
  
      override func numberOfSections(in tableView: UITableView) -&gt; Int {
          // #warning Incomplete implementation, return the number of sections
          return 1
      }
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
          // #warning Incomplete implementation, return the number of rows
          return idNumber.count
      }
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! idCell
          cell.idCell.text = "\(idNumber[indexPath.row])"
          return cell
      }
  
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if segue.identifier == "segue" {
              let nxtVC = segue.destination as? ViewController
              let myIndexPath = self.tableView.indexPathForSelectedRow!
              let row = myIndexPath.row
              nxtVC?.idNumber = idNumber[row]
          }
      }
  </code></pre>
  
  <p>When the cell from idTableView.swift is pressed it takes you to a new view with the single empty star button in the middle. </p>
  
  <p>ViewController.swift</p>
  
  <pre><code>import UIKit
  import CoreData
  
  class ViewController: UIViewController {
  
      var buttonIsSelected = false
  
      @IBOutlet var navigation: UINavigationItem!
      var idNumber: Int?
  
      @IBOutlet var onOffButton: UIButton!
      let image1 = UIImage(named: "empty") as UIImage?
      let image2 = UIImage(named: "filled") as UIImage?
  
      override func viewDidLoad() {
          super.viewDidLoad()
          getId()
  
      }
  //button Action
      @IBAction func onOffButtonPressed(_ sender: Any) {
          buttonIsSelected = !buttonIsSelected
          if buttonIsSelected == true {
              getFavorite(bool: buttonIsSelected)
              print("favorited")
              onOffButton.setImage(image2, for: .normal)
          } else if buttonIsSelected == false {
              getFavorite(bool: buttonIsSelected)
              print("unfavorited")
              onOffButton.setImage(image1, for: .normal)
          }
      }
      func getId() {
          if let id = idNumber {
              let newNumber = NSEntityDescription.insertNewObject(forEntityName: "IdNumber", into: PersistenceService.context) as! IdNumber
              let newBool = NSEntityDescription.insertNewObject(forEntityName: "Favorite", into: PersistenceService.context) as! Favorite
              newNumber.setValue(Int16(id), forKey: "idNumber")
              newBool.setValue(buttonIsSelected, forKey: "favorite")
              newNumber.favorite = newBool
              print("newNumber: \(newNumber.favorite)")
              print("newBool: \(newBool)")
              PersistenceService.saveContext()
              //self.navigationItem.title = "\(id)"
          }
      }
  
      func getFavorite(bool: Bool) {
          let newFavorite = NSEntityDescription.insertNewObject(forEntityName: "Favorite", into: PersistenceService.context)
          newFavorite.setValue(bool, forKey: "favorite")
          PersistenceService.saveContext()
      }
  </code></pre>
  
  <p>The thing i am seeing for core data is something like creating a workplace app where there are departments which are the parent and then people which populate the department. These apps create adepartment and then add people into that department that then populate a tableView. 
  What i am trying to do is different because my parent in this case is the id number and each id number has only one bool. When the bool is changed it changes the image of the button to a filled star. What i am having trouble doing is saving each bool to each id number. For example i have three id numbers, and each of those three id numbers can have a single bool, like 1: true, 2: false. 3: true. The default for each id number is false but when the button is pressed it should save the change of the bool which in turn changes the image of the button. </p>
  
  <p>I think the problem i am having is getting the relationship right in the code. It seems that i can do it for a single view, but when i go to a different view the app either crashes or something else, but the button state that i saved before changes to what it's default state is, which is false/ empty star button.</p>
  
  <p>If anyone has a question i will answer to the best of my ability. Thank you for the help.</p>