检索核心数据到tableview单元格swift [英] retrieving core data into tableview cells swift
问题描述
我试图简单地存储和检索CoreData(我在swift之前做过的事情)。我得到一个零的数据,但现在(不知道什么改变)我没有得到一个错误,只是没有显示在tableview。我不知道这是否存储或检索对象的问题。我跟着我是如何在我的另一个应用程序,尽可能接近,但似乎有一些基本的事情,我没有得到。这是我的。
我的模型:
import Foundation
import CoreData
@objc(DataModel)
class DataModel:NSManagedObject {
@NSManaged var itemName:String
@NSManaged var quantity: NSNumber
@NSManaged var price:NSNumber
}
我的tableviewcontroller和我想要保存数据的文本字段的静态单元格:
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()
//处理可以重新创建的任何资源。
}
@IBAction func saveButton(sender:AnyObject){
// CoreData
let appDelegate = UIApplication.sharedApplication()委托为AppDelegate
let managedContext:NSManagedObjectContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName(Item,inManagedObjectContext:managedContext)
var newItem = DataModel(entity:entity !, insertIntoManagedObjectContext:managedContext)
b $ b 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 )
}
在我的tableviewcontroller中,我想检索数据cell:
class ItemListTableViewController:UITableViewController {
pre>
var items:Array< AnyObject> = []
覆盖func viewDidLoad(){
super.viewDidLoad()
}
override func didReceiveMemoryWarning (){
super.didReceiveMemoryWarning()
//处理可以重新创建的任何资源。
}
// MARK: - 表视图数据源
override func numberOfSectionsInTableView(tableView:UITableView) - > Int {
// #warning潜在地不完整的方法实现。
//返回节的数量。
return 1
}
override func tableView(tableView:UITableView,numberOfRowsInSection section:Int) - > Int {
// #warning不完整的方法实现。
//返回节中的行数。
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
}
任何帮助一个概念我可能错过了在这里的某个地方将不胜感激!谢谢。
更新:所以我重新编写我的代码,以@Bluehound的建议。但我仍然得到一个错误:不知道如何解决它。
解决方案当使用核心数据和tableview时,应该使用
NSFetchedResultsController
。这基本上从核心数据检索数据,并通过section和indexPath组织它,因此它可以很容易地设置为tableView的数据源。下面是符合NSFetchedResultsControllerDelegate的潜在UITableViewController的完整实现:import Foundation
import UIKit
import CoreData
class HomeViewController:UITableViewController,NSFetchedResultsControllerDelegate {
let managedObjectContext:NSManagedObjectContext? =(UIApplication.sharedApplication()。delegate as?AppDelegate)?。managedObjectContext
var fetchedResultsController:NSFetchedResultsController?
override func viewDidLoad(){
super.viewDidLoad()
fetchedResultsController = NSFetchedResultsController(fetchRequest:allEmployeesFetchRequest(),managedObjectContext:managedObjectContext !, sectionNameKeyPath:nil, cacheName:nil)
fetchedResultsController?.delegate = self
fetchedResultsController?.performFetch(nil)
}
func allEmployeesFetchRequest - > NSFetchRequest {
var fetchRequest = NSFetchRequest(entityName:Employee)
let sortDescriptor = NSSortDescriptor(key:nameLast,ascending:true)
fetchRequest。 predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
return fetchRequest
}
// MARK: UITableView数据源和委托函数
override func numberOfSectionsInTableView(tableView:UITableView) - > Int {
return fetchedResultsController?.sections?.count? 0
}
override func tableView(tableView:UITableView,numberOfRowsInSection section:Int) - > Int {
return fetchedResultsController?.sections?[section] .numberOfObjects? 0
}
override func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath) - > UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(HomeCell,forIndexPath:indexPath)as UITableViewCell
如果let cellContact = fetchedResultsController?.objectAtIndexPath(indexPath)as?员工{
cell.textLabel?.text =\(cellContact.nameLast),\(cellContact.nameFirst)
}
$ b b返回单元
}
// MARK:NSFetchedResultsController委托函数
func controller(controller:NSFetchedResultsController,didChangeSection sectionInfo:NSFetchedResultsSectionInfo,atIndex sectionIndex:Int,forChangeType type:NSFetchedResultsChangeType){
开关类型{
case NSFetchedResultsChangeType.Insert:
tableView.insertSections(NSIndexSet(index:sectionIndex),withRowAnimation:UITableViewRowAnimation.Fade)
break
case NSFetchedResultsChangeType.Delete:
tableView.deleteSections(NSIndexSet(index:sectionIndex),withRowAnimation:UITableViewRowAnimation.Fade)
break
case NSFetchedResultsChangeType.Move:
break
case NSFetchedResultsChangeType.Update:
break
default:
break
}
}
override func tableView(tableView:UITableView,commitEditingStyle editingStyle:UITableViewCellEditingStyle ,forRowAtIndexPath indexPath:NSIndexPath){
如果editingStyle == .Delete {
}
切换editingStyle {
case .Delete:
managedObjectContext?.deleteObject (fetchedResultsController?.objectAtIndexPath(indexPath)as Employee)
managedObjectContext?.save(nil)
case .Insert:
break
case .None:
break
}
}
func controller(controller:NSFetchedResultsController,didChangeObject anObject:AnyObject,atIndexPath indexPath:NSIndexPath ?, forChangeType type:NSFetchedResultsChangeType,newIndexPath:NSIndexPath?){
switch type {
case NSFetchedResultsChangeType.Insert:
tableView.insertRowsAtIndexPaths(NSArray(object:newIndexPath!),withRowAnimation:UITableViewRowAnimation.Fade)
break
case NSFetchedResultsChangeType.Delete:
tableView.deleteRowsAtIndexPaths(NSArray(object:indexPath!),withRowAnimation:UITableViewRowAnimation.Fade)
break
case NSFetchedResultsChangeType.Move:
tableView.deleteRowsAtIndexPaths (object:indexPath!),withRowAnimation:UITableViewRowAnimation.Fade)
tableView.insertRowsAtIndexPaths(NSArray(object:newIndexPath!),withRowAnimation:UITableViewRowAnimation.Fade)
break
case NSFetchedResultsChangeType.Update:
tableView.cellForRowAtIndexPath(indexPath!)
break
默认值:
break
}
}
func controllerWillChangeContent(controller:NSFetchedResultsController ){
tableView.beginUpdates()
}
func controllerDidChangeContent(controller:NSFetchedResultsController){
tableView.endUpdates()
}
}
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:import Foundation import UIKit import CoreData class HomeViewController: UITableViewController, NSFetchedResultsControllerDelegate { let managedObjectContext: NSManagedObjectContext? = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext var fetchedResultsController: NSFetchedResultsController? override func viewDidLoad() { super.viewDidLoad() fetchedResultsController = NSFetchedResultsController(fetchRequest: allEmployeesFetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil) fetchedResultsController?.delegate = self fetchedResultsController?.performFetch(nil) } func allEmployeesFetchRequest() -> NSFetchRequest { var fetchRequest = NSFetchRequest(entityName: "Employee") let sortDescriptor = NSSortDescriptor(key: "nameLast", ascending: true) fetchRequest.predicate = nil fetchRequest.sortDescriptors = [sortDescriptor] fetchRequest.fetchBatchSize = 20 return fetchRequest } //MARK: UITableView Data Source and Delegate Functions override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return fetchedResultsController?.sections?.count ?? 0 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return fetchedResultsController?.sections?[section].numberOfObjects ?? 0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("HomeCell", forIndexPath: indexPath) as UITableViewCell if let cellContact = fetchedResultsController?.objectAtIndexPath(indexPath) as? Employee { cell.textLabel?.text = "\(cellContact.nameLast), \(cellContact.nameFirst)" } return cell } //MARK: NSFetchedResultsController Delegate Functions func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { switch type { case NSFetchedResultsChangeType.Insert: tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade) break case NSFetchedResultsChangeType.Delete: tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade) break case NSFetchedResultsChangeType.Move: break case NSFetchedResultsChangeType.Update: break default: break } } override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { if editingStyle == .Delete { } switch editingStyle { case .Delete: managedObjectContext?.deleteObject(fetchedResultsController?.objectAtIndexPath(indexPath) as Employee) managedObjectContext?.save(nil) case .Insert: break case .None: break } } func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { switch type { case NSFetchedResultsChangeType.Insert: tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!), withRowAnimation: UITableViewRowAnimation.Fade) break case NSFetchedResultsChangeType.Delete: tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!), withRowAnimation: UITableViewRowAnimation.Fade) break case NSFetchedResultsChangeType.Move: tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!), withRowAnimation: UITableViewRowAnimation.Fade) tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!), withRowAnimation: UITableViewRowAnimation.Fade) break case NSFetchedResultsChangeType.Update: tableView.cellForRowAtIndexPath(indexPath!) break default: break } } func controllerWillChangeContent(controller: NSFetchedResultsController) { tableView.beginUpdates() } func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.endUpdates() } }
See a sample GitHub project here.
这篇关于检索核心数据到tableview单元格swift的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!