Ok I am brand new to this and am a bit overwhelmed going through many tutorials and articles. And spent a few hours sorting through similar issues with no luck in fixing my own. I have a "AddSiteVC" to allow the user to add or delete Items that are put into CoreData and then displayed in a TableView on my "MainVC". My problem is when I press save or delete and get dismissed back to my MainVC onBtnClick the TableView doesn't update until I leave the MainVC and then come back. I don't know what I'm doing wrong but can't seem to find anything that fixes this... I don't know where my problem is so I'll include most of my MainVC code for reference.
Any help would be greatly appreciated!
Thanks!
import UIKit
import CoreData
class SitesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var controller: NSFetchedResultsController<Sites>!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
attemptFetch()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SitesCell", for: indexPath) as! SitesCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return UITableViewCell()
}
func configureCell(cell: SitesCell, indexPath: NSIndexPath) {
let sites = controller.object(at: indexPath as IndexPath)
cell.configureCell(sites: sites)
cell.accessoryType = .detailButton
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddSiteViewController" {
if let destination = segue.destination as? AddSiteViewController {
if let site = sender as? Sites {
destination.siteToEdit = site
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = controller.sections {
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if let sections = controller.sections {
return sections.count
}
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 75
}
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let site = objs[indexPath.row]
performSegue(withIdentifier: "AddSiteViewController", sender: site)
}
}
func attemptFetch() {
let fetchRequest: NSFetchRequest<Sites> = Sites.fetchRequest()
let alphebaticalSort = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [alphebaticalSort]
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = self
self.controller = controller
do {
try controller.performFetch()
} catch {
let error = error as NSError
print("\(error)")
}
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch (type) {
case.insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
case.delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break
case.update:
if let indexPath = indexPath {
let cell = tableView.cellForRow(at: indexPath) as! SitesCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
}
break
case.move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
}
Please make following change in the code . Because viewDidLoad will be called when viewcontroller is loaded . But as per your requirement you adding something in Modal page. So you need move the code to viewWillAppear
import UIKit
import CoreData
class SitesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var controller: NSFetchedResultsController<Sites>!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
attemptFetch()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SitesCell", for: indexPath) as! SitesCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return cell }
Related
I created UITableViewController programmatically but methods for deleting rows editingStyle and didSelectRowAt not working. I cannot figure out why they don't work. I checked everything and tried by anywahy delegate methods not work.
My code:
import UIKit
class FPTasksViewController: UITableViewController, FPPopUpViewControllerDelegate {
let date = String(DateFormatter.localizedString(from: NSDate() as Date, dateStyle: .long, timeStyle: .none))
private var tasks: [FPTask] = FPDefaults.sh.tasks {
didSet {
FPDefaults.sh.tasks = self.tasks
}
}
// MARK: - life cycle functions
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .none
let tapGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(didTapTableView))
tableView.addGestureRecognizer(tapGestureRecognizer)
}
// MARK: - actions
func FPPopUpViewControllerOkButtonTapped(_ controller: FPPopUpViewController, didFinishAdding newTask: FPTask) {
let newRowIndex = tasks.count
self.tasks.append(newTask)
let indexPath = IndexPath(row: newRowIndex, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
navigationController?.popViewController(animated: true)
}
#objc func addButtonTapped() {
let popUp = FPPopUpViewController()
popUp.delegate = self
self.view.addSubview(popUp)
self.view.backgroundColor = UIColor.systemGray3.withAlphaComponent(0.8)
}
#objc func didTapTableView(_ gestureRecognizer: UILongPressGestureRecognizer) {
self.tableView.backgroundColor = .black
}
// MARK: - table view
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
self.tasks.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
default:
break
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tasks.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: FPTasksCell.reuseIdentifier,
for: indexPath) as? FPTasksCell ?? FPTasksCell()
let task = tasks[indexPath.row]
cell.setCellData(taskName: " \(task.taskTitle)", taskDescription: " from \(date.lowercased())")
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(1)
}
}
Why I cannot delete rows? And how to make didSelectRowAt method works also? What I did wrong?
set tableView datasource and delegate in viewDidLoad method.
self.tableView.delegate = self
self.tableView.dataSource = self
class FPTasksViewController: UITableViewController, FPPopUpViewControllerDelegate, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tableView.delegate = self
self.tableView.dataSource = self
}
}
When I run the app, I am able to populate the cells in my tableview but when I save (from a separate view controller) and go back to the tableview controller, tableView.reloadData() gets called but nothing happens. I use the notification center to reload the data before popping back.
TableViewController.swift:
lazy var fetchedResultsController: NSFetchedResultsController<Pet> = {
let fetchRequest = PersistenceManager.shared.fetchRequest()
let context = PersistenceManager.shared.context
let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
return frc as! NSFetchedResultsController<Pet>
}()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(pushToAddPetViewController))
tableView.register(MainTableViewCell.self, forCellReuseIdentifier: "cell")
do {
try fetchedResultsController.performFetch()
tableView.reloadData()
} catch let err {
print(err)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
}
#objc func loadList(notification: NSNotification){
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
AddPetVC.swift:
func saveContext() {
// Inputs saved to coreData
PersistenceManager.shared.saveContext()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
self.navigationController?.popViewController(animated: true)
}
You fetched data in viewDidLoad() which will not be called when you come back to the view. You should fetch data in viewWillAppear() and reload from that or from the notification observer method loadList(notification: NSNotification) . So, add the below code in viewWillAppear() or loadList(notification: NSNotification) :
do {
try fetchedResultsController.performFetch()
tableView.reloadData()
} catch let err {
print(err)
}
When you popViewController to call back to previous ViewController, viewWillAppear() will not be called.
Create fetchedResultsController instance and conform to NSFetchedResultsControllerDelegate. NSFetchedResultsControllerDelegate will observe the changes and reflect changes on UI
lazy var fetchedResultsController: NSFetchedResultsController<Pet> = {
let fetchRequest = PersistenceManager.shared.fetchRequest()
let context = PersistenceManager.shared.context
let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
frc.delegate = self
return frc as! NSFetchedResultsController<Pet>
}()
In your viewDidLoad
do {
try fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("Unable to Save Note")
print("\(fetchError), \(fetchError.localizedDescription)")
}
Now implement NSFetchedResultsControllerDelegate
extension YourController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
uiTableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
uiTableView.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 {
uiTableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
uiTableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
if let indexPath = indexPath, let cell = uiTableView.cellForRow(at: indexPath) as? UserCell {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
uiTableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
uiTableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
}
}
}
Implement UITableViewDataSource & UITableViewDelegate
extension YourController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let sections = fetchedResultsController.sections else {
return 0
}
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PetCell", for: indexPath) as! Pet
configureCell(cell, at: indexPath)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pet = fetchedResultsController.object(at: indexPath)
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
// handle delete (by removing the data from your array and updating the tableview)
//let user = viewModel.user(for: indexPath.row)
let pet = fetchedResultsController.object(at: indexPath)
//Delete pet and reload table
}
}
func configureCell(_ cell: Pet, at indexPath: IndexPath) {
let pet = fetchedResultsController.object(at: indexPath)
}
For more details and code follow the demo project
https://github.com/rheyansh/CoreDataDemo
I have a tableview which I can add items to it and it will save to core data, I can also delete these items and it all works fine
However now I want to rearrange the cells and persist the data as well
At the moment I can select the barbutton Edit and it will allow me to rearrange the cells but the moment i leave the viewcontroller it will reset to how it was
Can someone please help me?
class CustomWorkoutViewController: UIViewController {
#IBOutlet weak var newMusclesTableView: UITableView!
var workout:Workout?
override func viewDidLoad() {
super.viewDidLoad()
newMusclesTableView.delegate = self
let nib = UINib(nibName: "muscleListTableViewCell", bundle: nil)
newMusclesTableView.register(nib, forCellReuseIdentifier: "workCell")
}
override func viewDidAppear(_ animated: Bool) {
self.newMusclesTableView.reloadData()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addMuscles"{
guard let destination = segue.destination as? AddMusclesViewController else {
return
}
destination.workout = workout
}
else if segue.identifier == "addLogs"{
guard let destination = segue.destination as? WorkoutViewController,
let selectedRow = self.newMusclesTableView.indexPathForSelectedRow?.row else {
return
}
destination.muscleLog = workout?.muscleList?[selectedRow]
}
}
func btnAction(_ sender: UIButton) {
let point = sender.convert(CGPoint.zero, to: newMusclesTableView as UIView)
let indexPath: IndexPath! = newMusclesTableView.indexPathForRow(at: point)
let vc = viewMusclesViewController()
let viewTitle = workout?.muscleList?[indexPath.row]
vc.customInit(title: (viewTitle?.name)!)
vc.titleStr = viewTitle?.name
vc.gifStr = viewTitle?.muscleImage
navigationController?.pushViewController(vc, animated: true)
}
#IBAction func editAction(_ sender: UIBarButtonItem) {
self.newMusclesTableView.isEditing = !self.newMusclesTableView.isEditing
sender.title = (self.newMusclesTableView.isEditing) ? "Done" : "Edit"
}
func deleteMuscle(at indexPath: IndexPath){
guard let muscles = workout?.muscleList?[indexPath.row],
let managedContext = muscles.managedObjectContext else{
return
}
managedContext.delete(muscles)
do{
try managedContext.save()
newMusclesTableView.deleteRows(at: [indexPath], with: .automatic)
}catch{
print("Could not save")
newMusclesTableView.reloadRows(at: [indexPath], with: .automatic)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And this is my tableview extension
extension CustomWorkoutViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return workout?.muscleList?.count ?? 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = newMusclesTableView.dequeueReusableCell(withIdentifier: "muscleCell", for: indexPath) as? muscleListTableViewCell
cell?.cellView.layer.cornerRadius = (cell?.cellView.frame.height)! / 2
if let muscles = workout?.muscleList?[indexPath.row]{
cell?.muscleTitle?.text = muscles.name
cell?.myBtn.addTarget(self, action: #selector(self.btnAction(_:)), for: .touchUpInside)
}
return cell!
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete{
deleteMuscle(at: indexPath)
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
//How to persist data here?
}
}
Your code decides which item to display for a row with this code:
if let muscles = workout?.muscleList?[indexPath.row]
The row order is going to be determined by the order in muscleList. The table view can rearrange cells when you use its edit mode, but it can't save that new order because it doesn't know how to change the order of muscleList. Your implementation of tableView(_:moveRowAt:to:) needs to change the order based on the table view update.
If muscleList is an ordered relationship, change the order. If it's not an ordered relationship then you'll need to add a property that you can use to sort the relationship-- even something as simple as a sortOrder property would do.
I managed to find a solution to my own question
I will post it here for future if anyone needed help
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let muscle = workout?.muscleList?[sourceIndexPath.row]
workout?.removeFromRawMuscles(at: sourceIndexPath.row)
workout?.insertIntoRawMuscles(muscle!, at: destinationIndexPath.row)
do{
try muscle?.managedObjectContext?.save()
}catch{
print("Rows could not be saved")
}
}
I'm a beginner in IOS development in swift. The problem I am facing is: I am building an app using CoreData and the app contains table view and table cell. I can't really explain because of my lack of knowledge so I'm sharing screenshots. I have seen other Questions asked, none of them solved my error. and I have also made a function for context in AppDelegate which is
#available(iOS 10.0, *)
let ad = UIApplication.shared.delegate as! AppDelegate
#available(iOS 10.0, *)
let context = ad.persistentContainer.viewContext
my code for VC is
import UIKit
import CoreData
class MainVC: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
#IBOutlet weak var tableViewmain: UITableView!
#IBOutlet weak var topSegment: UISegmentedControl!
var fetchResultControll: NSFetchedResultsController<Items>!
override func viewDidLoad() {
super.viewDidLoad()
tableViewmain.delegate = self
tableViewmain.dataSource = self
doFetch()
}
func configureCell (cell: ItemsCell, indexPath: IndexPath) {
let item = fetchResultControll.object(at: indexPath) // remember as here
cell.confugringCell(item: item)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewmain.dequeueReusableCell(withIdentifier: "ItemsCell", for: indexPath) as! ItemsCell
configureCell(cell: cell, indexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchResultControll.sections{
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if let allSections = fetchResultControll.sections {
return allSections.count
}
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func doFetch() {
let fetchRequest: NSFetchRequest<Items> = Items.fetchRequest()
let dateSrot = NSSortDescriptor(key: "created", ascending: false)
fetchRequest.sortDescriptors = [dateSrot]
if #available(iOS 10.0, *) {
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
do {
try controller.performFetch()
}
catch {
let err = error as NSError
print("\(err)")
}
} else {
// Fallback on earlier versions
}
}
//controler willchnge
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableViewmain.beginUpdates()
}
//controlerdidchnge
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableViewmain.endUpdates()
}
//controlerdidchangeanobject
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch(type) {
case .insert:
if let indexpath = newIndexPath {
tableViewmain.insertRows(at: [indexpath], with: .fade)
}
break
case .delete:
if let indexpath = indexPath {
tableViewmain.deleteRows(at: [indexpath], with: .fade)
}
break
case .update:
if let indexpath = indexPath {
let cell = tableViewmain.cellForRow(at: indexpath) as! ItemsCell
configureCell(cell: cell, indexPath: indexpath) // as used here
}
break
case .move:
if let indexpath = indexPath {
tableViewmain.deleteRows(at: [indexpath], with: .fade)
}
if let indexpath = newIndexPath {
tableViewmain.insertRows(at: [indexpath], with: .fade)
}
break
}
}
I hope you understand me.. Any Help would be highly appreciated
Replace following line with your .
var fetchResultControll: NSFetchedResultsController<Items>?
i am facing an issue in IOS swift Xcode 8
after i setup my Core Data and before i insert any junk data in purpose of testing the fetch function the app run correctly with no crash and no data but after i insert a data the app crash with below message
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UITableViewCell 0x7f9b26054c00> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Deatials.
here is my code
//
import UIKit
import CoreData
// the NSFetchedResultsControllerDelegate needed to start woring in all the function for datacore
class MainVC: UIViewController , UITableViewDelegate, UITableViewDataSource,NSFetchedResultsControllerDelegate{
// definning the main view the table and the segment.
#IBOutlet weak var TableView: UITableView!
#IBOutlet weak var segment: UISegmentedControl!
// need to difine the NSFetchedResultsController to define the remaining 3 functions for the tableview
var controller : NSFetchedResultsController<Item>!
override func viewDidLoad() {
super.viewDidLoad()
generateTeseData()
attemptFetch()
TableView.dataSource = self
TableView.delegate = self
}
// we need to define 3 main fucntions for the table view
func numberOfSections(in tableView: UITableView) -> Int {
if let sections = controller.sections{
return sections.count
}
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// need to difine number of rows in section by NSFetchedResultsController
if let sections = controller.sections{
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// linking the cell var with the class of itemCell been created in the View Folder
let cell = tableView.dequeueReusableCell(withIdentifier: "CellItem", for: indexPath) as! ItemCell
// function been created below:
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func configureCell (cell:ItemCell, indexPath: NSIndexPath){
let item = controller.object(at: indexPath as IndexPath)
cell.ConfigureCellsInCellclass(item: item)
}
func attemptFetch () {
let fetchrequest:NSFetchRequest<Item> = Item.fetchRequest()
let datesort = NSSortDescriptor(key: "created", ascending: false)
fetchrequest.sortDescriptors = [datesort]
let controller = NSFetchedResultsController(fetchRequest: fetchrequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
self.controller = controller
do{
try controller.performFetch()
}catch{
let error = error as NSError
print("\(error)")
}
}
// these two function for the update in the tableview
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
TableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
TableView.endUpdates()
}
//this function to preforme all the functions for the <Data Core>
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch(type)
{
case.insert:
if let indexpath = newIndexPath {
TableView.insertRows(at: [indexpath], with: .fade)
}
break
case.delete:
if let indexpath = indexPath{
TableView.deleteRows(at: [indexpath], with: .fade)
}
break
case.update:
if let indexpath = indexPath {
let cell = TableView.cellForRow(at: indexpath) as! ItemCell
configureCell(cell: cell, indexPath: indexPath! as NSIndexPath)
}
break
case.move:
if let indexpath = indexPath {
TableView.deleteRows(at: [indexpath], with: .fade)
}
if let indexpath = indexPath {
TableView.insertRows(at: [indexpath], with: .fade)
}
break
}
}
at this point the system will cun without any crash
but after i add the insert function in below it's start crashing
func generateTeseData(){
let item = Item(context: context)
item.title = "IMAC"
item.price = 2000
item.details = "Soon"
}
this is my view cell file
class ItemCell: UITableViewCell {
// this view to take all the label from the view and link it here
#IBOutlet weak var thump: UIImageView!
#IBOutlet weak var Title: UILabel!
#IBOutlet weak var Price: UILabel!
#IBOutlet weak var Deatials: UILabel!
// using this function to set the values of the items with the labels been linked before in upper section
func ConfigureCellsInCellclass (item:Item){
Title.text = item.title
Price.text = ("$\(item.price)")
Deatials.text = item.details
}
}
thank you guys in advance
As #Larme says your problem is related to IBOutlet which is not reflect in class anymore.
Disconnect bad outlet