Okay, so I've done a ton of searching and everything I'm finding seems to have to do with View Controllers and the links on them not working or not being connected. That is not my problem. I have an app that's using CoreData to keep tabs on a list of Tables, their Table Numbers, if they're clean or not, and if they're in use or not. However, when I try to change the key value of an attribute using the setValue() function, it's crashing my app saying the following crash report
2018-04-02 21:45:15.840265-0500 Trakr[26636:1455153] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSManagedObjectContext 0x6040001c4fb0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inUse.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010d1af1e6 __exceptionPreprocess + 294
1 libobjc.A.dylib 0x0000000108f3d031 objc_exception_throw + 48
2 CoreFoundation 0x000000010d1af0b9 -[NSException raise] + 9
3 Foundation 0x000000010895eb47 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 292
4 Trakr 0x0000000108615bee _T05Trakr24CheckTableViewControllerC18inUseSwitchChangedyypF + 846
5 Trakr 0x0000000108615e41 _T05Trakr24CheckTableViewControllerC18inUseSwitchChangedyypFTo + 81
6 UIKit 0x000000010ac1a448 -[UIApplication sendAction:to:from:forEvent:] + 83
7 UIKit 0x000000010ad95804 -[UIControl sendAction:to:forEvent:] + 67
8 UIKit 0x000000010ad95b21 -[UIControl _sendActionsForEvents:withEvent:] + 450
9 UIKit 0x000000010b8d6d60 -[UISwitchModernVisualElement sendStateChangeActions] + 73
10 UIKit 0x000000010b29889f -[UISwitchMVEGestureTrackingSession _sendStateChangeActionsIfNecessary] + 63
11 UIKit 0x000000010b8d74ec -[UISwitchModernVisualElement _handleLongPressWithGestureLocationInBounds:gestureState:] + 760
12 UIKit 0x000000010b21141b -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 57
13 UIKit 0x000000010b21a1f0 _UIGestureRecognizerSendTargetActions + 109
14 UIKit 0x000000010b217a38 _UIGestureRecognizerSendActions + 307
15 UIKit 0x000000010b216c8c -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 859
16 UIKit 0x000000010b1fbcf0 _UIGestureEnvironmentUpdate + 1329
17 UIKit 0x000000010b1fb773 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 484
18 UIKit 0x000000010b1fa875 -[UIGestureEnvironment _updateGesturesForEvent:window:] + 281
19 UIKit 0x000000010ac9080b -[UIWindow sendEvent:] + 4064
20 UIKit 0x000000010ac34370 -[UIApplication sendEvent:] + 352
21 UIKit 0x000000010b57557f __dispatchPreprocessedEventFromEventQueue + 2796
22 UIKit 0x000000010b578194 __handleEventQueueInternal + 5949
23 CoreFoundation 0x000000010d151bb1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
24 CoreFoundation 0x000000010d1364af __CFRunLoopDoSources0 + 271
25 CoreFoundation 0x000000010d135a6f __CFRunLoopRun + 1263
26 CoreFoundation 0x000000010d13530b CFRunLoopRunSpecific + 635
27 GraphicsServices 0x000000010fa46a73 GSEventRunModal + 62
28 UIKit 0x000000010ac190b7 UIApplicationMain + 159
29 Trakr 0x000000010861e697 main + 55
30 libdyld.dylib 0x000000010e318955 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I cannot for the life of me figure out why this is happening. Here is my view controller class:
import UIKit
import CoreData
class CheckTableViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var backgroundImage: UIImageView!
@IBOutlet weak var pickerView: UIPickerView!
@IBOutlet weak var tableNumberLabel: UILabel!
@IBOutlet weak var cleanSwitch: UISwitch!
@IBOutlet weak var inUseSwitch: UISwitch!
var tablesList = [Table]()
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
let fetchRequest: NSFetchRequest<Table> = Table.fetchRequest()
do {
let tablesList = try PersistenceService.context.fetch(fetchRequest)
self.tablesList = tablesList
} catch {}
backgroundImage.addBlurEffect()
tableNumberLabel.text = "Select a Table"
cleanSwitch.isEnabled = false
inUseSwitch.isEnabled = false
if tablesList.isEmpty {
pickerView.isHidden = true
tableNumberLabel.text = "Add Some Tables"
} else {
pickerView.isHidden = false
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Picker View and Switch Controlls
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return tablesList.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(tablesList[row].tableNumber)
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if (tablesList.isEmpty) {
tableNumberLabel.text = "Add a table"
} else {
tableNumberLabel.text = String(tablesList[row].tableNumber)
if cleanSwitch.isEnabled == false {
cleanSwitch.isEnabled = true
}
if inUseSwitch.isEnabled == false {
inUseSwitch.isEnabled = true
}
if tablesList[row].isClean == true {
cleanSwitch.isOn = true
} else {
cleanSwitch.isOn = false
}
if tablesList[row].inUse == true{
inUseSwitch.isOn = true
} else {
inUseSwitch.isOn = false
}
}
}
@IBAction func cleanSwitchChanged(_ sender: Any) {
if cleanSwitch.isOn == false {
PersistenceService.context.setValue(false, forKey: "isClean")
} else {
PersistenceService.context.setValue(true, forKey: "isClean")
}
}
@IBAction func inUseSwitchChanged(_ sender: Any) {
if inUseSwitch.isOn == false {
let selectedRow = pickerView.selectedRow(inComponent: 0)
tablesList[selectedRow].inUse = false
PersistenceService.context.setValue(false, forKey: "inUse")
} else {
let selectedRow = pickerView.selectedRow(inComponent: 0)
tablesList[selectedRow].inUse = true
PersistenceService.context.setValue(true, forKey: "inUse")
}
}
}
And here is my PersistenceService class, the one responsible for CoreData functionality
import Foundation
import CoreData
class PersistenceService {
// MARK: - Core Data stack
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: "tableModel")
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 to CoreData")
} 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)")
}
}
}
}
And finally, a screenshot of my tableModel CoreData Model
Can someone tell me why this isn't working? I can't understand it for the life of me....