I am trying to simply store and retrieve CoreData (something that I've done successfully before with swift). I was getting a nil for data, but now (not sure what changed) I'm not getting an error, just nothing showing in the tableview. I'm not sure if it's a problem in storing or retrieving the object. I've followed how I did it in another app of mine as closely as possible, but there seems to be some fundamental thing that I'm not getting. Here's what I have.
My model:
import Foundation
import CoreData
@objc(DataModel)
class DataModel: NSManagedObject {
@NSManaged var itemName: String
@NSManaged var quantity: NSNumber
@NSManaged var price: NSNumber
}
In my tableviewcontroller with static cells for text fields that I want to save data from:
import UIKit
import CoreData
class NewItemTableViewController: UITableViewController {
@IBOutlet weak var itemNameTextField: UITextField!
@IBOutlet weak var itemPriceTextField: UITextField!
@IBOutlet weak var itemQuantityTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func saveButton(sender: AnyObject) {
//CoreData
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext : NSManagedObjectContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Item", inManagedObjectContext: managedContext)
var newItem = DataModel(entity: entity!, insertIntoManagedObjectContext: managedContext)
newItem.itemName = itemNameTextField.text
//newItem.price = itemPriceTextField.text
//newItem.quantity = itemQuantityTextField
managedContext.save(nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
@IBAction func cancelButton(sender: AnyObject) {
self.navigationController?.popToRootViewControllerAnimated(true)
}
And in my tableviewcontroller that I want to retrieve the data an show in dynamic cells:
class ItemListTableViewController: UITableViewController {
var items : Array<AnyObject> = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID: NSString = "cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell
var data: NSManagedObject = items[indexPath.row] as NSManagedObject
var itemName = data.valueForKey("itemName") as String
var price = data.valueForKey("price") as NSNumber
var quantity = data.valueForKey("quantity") as NSNumber
cell.textLabel!.text! = "\(itemName)"
cell.detailTextLabel!.text! = "Price: \(price) - Quantity: \(quantity)"
return cell
}
Any help on a concept I might have missed somewhere in here would be appreciated! Thanks.
Update: so I've redone my code to be modeled after @Bluehound 's suggestion. but I'm still getting an error: not sure how to fix it.
When using core data and a tableview, you should use
NSFetchedResultsController
. This essentially retrieves data from core data and organizes it by section and indexPath so it can easily be set as the data source of the tableView. Here is a complete implementation of a potential UITableViewController that conforms to NSFetchedResultsControllerDelegate:See a sample GitHub project here.