我需要用我的核心数据中的数据填充我的 TableView 。 我可以显示我的行,但是我无法填充我的表格 View ! 我使用 Swift 3 和 Xcode 8。 这是我的代码,在这个 Controller 中我必须显示列表。
class iTableViewController: UITableViewController, NSFetchedResultsControllerDelegate{
@IBOutlet var iTableView: UITableView!
override func viewDidLoad(){
super.viewDidLoad()
iTableView.dataSource = self
iTableView.delegate = self
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managerContext = appDelegate.persistentContainer.viewContext
let interventsFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Intervento")
do{
//results
let fetchedIntervents = try managerContext.fetch(interventsFetch) as! [Intervento]
for interv in fetchedIntervents{
print(interv.stampRow())
}
NSLog(String(fetchedIntervents.count))
}catch{
fatalError("Failed to fetch employees: \(error)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//number of sections
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//numer of rows
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
//cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "cell")
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
//print the example cell
cell.textLabel?.text = "title"
cell.detailTextLabel?.text = "subtitle"
return cell
}
//swipe and delete
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if(editingStyle == UITableViewCellEditingStyle.delete){
//TODO
}
}
// click cell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
performSegue(withIdentifier: "segueDetail", sender: self)
}
override func viewDidAppear(_ animated: Bool){
//iTableView.reloadData()
}
override func viewWillDisappear(_ animated: Bool) {
//iTableView.reloadData()
//fetchData()
}
}
这是我的类(class)
extension Intervento {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Intervento> {
return NSFetchRequest<Intervento>(entityName: "Intervento");
}
@NSManaged public var cliente: Int32
@NSManaged public var dataFine: String?
@NSManaged public var dataInizio: String?
@NSManaged public var descrizione: String?
@NSManaged public var foto: String?
@NSManaged public var id: Int32
@NSManaged public var stato: String?
@NSManaged public var tecnico: String?
func stampRow()->String{
let v1 = String(id) + " " + String(cliente) + " "
let v2 = dataInizio! + " " + dataFine! + " "
let v3 = stato! + " " + tecnico! + " " + descrizione!
return v1 + v2 + v3
}
}
这是我保存数据的代码(有效)
@IBAction func addButton(_ sender: Any){
//genero la data
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy HH:mm"
let strDate = dateFormatter.string(from: myDatePicker.date)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managerContext = appDelegate.persistentContainer.viewContext
let newInt = NSEntityDescription.insertNewObject(forEntityName: "Intervento", into: managerContext)
newInt.setValue(1, forKey: "id")
newInt.setValue(strDate, forKey: "dataInizio")
newInt.setValue("", forKey: "dataFine")
newInt.setValue(2, forKey: "cliente")
newInt.setValue("Matt", forKey: "tecnico")
newInt.setValue(stato[1], forKey: "stato")
newInt.setValue("", forKey: "descrizione")
newInt.setValue("", forKey: "foto")
do{
try managerContext.save()
print("saved")
}catch let error as NSError{
//errore salvataggio
print("Could not fetch \(error), \(error.userInfo)")
}
}
最佳答案
首先,你的类应该实现这个协议(protocol):
UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate
您可以使用以下代码从持久存储中加载数据:
//load data
//persistant container
let persistentContainer = NSPersistentContainer.init(name: "Model")
//
lazy var fetchedResultsController: NSFetchedResultsController<Intervento> = {
// Create Fetch Request
let fetchRequest: NSFetchRequest<Intervento> = Intervento.fetchRequest()
// Configure Fetch Request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "dataInizio", ascending: false)]
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managerContext = appDelegate.persistentContainer.viewContext
// Create Fetched Results Controller
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managerContext, sectionNameKeyPath: nil, cacheName: nil)
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
return fetchedResultsController
}()
//carica
func load(){
//persistant container
persistentContainer.loadPersistentStores { (persistentStoreDescription, error) in
if let error = error {
print("Unable to Load Persistent Store")
print("\(error), \(error.localizedDescription)")
} else {
do {
try self.fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("Unable to Perform Fetch Request")
print("\(fetchError), \(fetchError.localizedDescription)")
}
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
iTableView.delegate = self
iTableView.dataSource = self
// trigger load
load()
}
你的数据将被获取并显示出来,因为你已经通过这行代码委托(delegate)了 iTableViewController:
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
为了使它工作,你的 ViewController 必须符合 NSFetchedResultsControllerDelegate 协议(protocol),在这里你可以找到一个可能的实现:
extension iTableViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
iTableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
iTableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch (type) {
case .insert:
if let indexPath = newIndexPath {
iTableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
iTableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
if let indexPath = indexPath, let cell = iTableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
iTableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
iTableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
}
}
}
总而言之,这是您的 iTableViewController 的完整实现(我还包含了删除行的必要代码):
class iTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
@IBOutlet var iTableView: UITableView!
//load data
//persistant container
let persistentContainer = NSPersistentContainer.init(name: "Model")
//
lazy var fetchedResultsController: NSFetchedResultsController<Intervento> = {
// Create Fetch Request
let fetchRequest: NSFetchRequest<Intervento> = Intervento.fetchRequest()
// Configure Fetch Request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "dataInizio", ascending: false)]
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managerContext = appDelegate.persistentContainer.viewContext
// Create Fetched Results Controller
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managerContext, sectionNameKeyPath: nil, cacheName: nil)
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
return fetchedResultsController
}()
//carica
func load(){
//persistant container
persistentContainer.loadPersistentStores { (persistentStoreDescription, error) in
if let error = error {
print("Unable to Load Persistent Store")
print("\(error), \(error.localizedDescription)")
} else {
do {
try self.fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("Unable to Perform Fetch Request")
print("\(fetchError), \(fetchError.localizedDescription)")
}
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
iTableView.delegate = self
iTableView.dataSource = self
// trigger load
load()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//numero di sezioni
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//numero di righe
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let quotes = fetchedResultsController.fetchedObjects else { return 0 }
return quotes.count
}
//gestisco la cella
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//genero la cella
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "cell")
configureCell(cell, at:indexPath)
return cell
}
//swipe and delete
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if(editingStyle == .delete){
// Fetch Quote
let quote = fetchedResultsController.object(at: indexPath)
// Delete Quote
quote.managedObjectContext?.delete(quote)
}
}
// click cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
performSegue(withIdentifier: "segueDetail", sender: self)
}
func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
//get intervento
let intervento = fetchedResultsController.object(at: indexPath)
//fill the cell
cell.textLabel?.text = intervento.dataInizio
cell.detailTextLabel?.text = "SOME_THING"
}
//quando appare aggiorno la table view
override func viewDidAppear(_ animated: Bool){
self.iTableView.reloadData()
}
}
extension iTableViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
iTableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
iTableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch (type) {
case .insert:
if let indexPath = newIndexPath {
iTableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
iTableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
if let indexPath = indexPath, let cell = iTableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
iTableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
iTableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
}
}
}
在对数据进行操作时(例如添加新数据时),不要忘记始终使用相同的上下文。
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managerContext = appDelegate.persistentContainer.viewContext
有关完整示例,您应该查看此处:https://github.com/bartjacobs/ExploringTheFetchedResultsControllerDelegateProtocol
关于swift - 使用 NSFetchRequest 从 CoreData 填充 TableView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42676625/