Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

xcode - How to delete row in table view core Data. Swift 3

I been researching how to delete a row from a table view which the data is in Core Data. I can't find anything online that would help me with my code. Im really new with Core Data so I don't really understand much of it.

Thanks in advance

This is my Code

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return}

    let managedContext = appDelegate.persistentContainer.viewContext

    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "OfficialPT")
    fetchRequest.sortDescriptors = [NSSortDescriptor(key:"createdAt",ascending:false)]


    do {
        AirForceDatabase = try managedContext.fetch(fetchRequest)
    } catch let error as NSError {
        print("Could not fetch. (error), (error.userInfo)")
    }
}

func SideMenus ()
{
    if revealViewController() != nil {
        MenuButton.target = revealViewController()
        MenuButton.action = #selector(SWRevealViewController.revealToggle(_:))
        revealViewController().rearViewRevealWidth = 275
        revealViewController().rightViewRevealWidth = 160

        // profileButton.target = revealViewController()
        // profileButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))

        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())


    }
}

}

extension HistoryPTViewController: UITableViewDataSource {

func tableView(_ tableView: UITableView,
               numberOfRowsInSection section: Int) -> Int {
    return AirForceDatabase.count
}


func tableView(_ tableView: UITableView,
               cellForRowAt indexPath: IndexPath) -> UITableViewCell {




    if let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? HistoryPTTableViewCell {


    let person = AirForceDatabase[indexPath.row]

       cell.OfficialAbsLbl!.text = person.value(forKeyPath: "officialAbs")! as? String
        cell.OfficialPushLbl!.text = person.value(forKeyPath: "officialPush")! as? String
        cell.OfficialSitLbl!.text = person.value(forKeyPath: "officialSit")! as? String
        cell.OfficialRunLbl!.text = person.value(forKeyPath: "officialRun")! as? String
        cell.officialTotal!.text = person.value(forKeyPath: "totalScore")! as? String
        cell.officialdateCreated.text = person.value(forKeyPath: "createdAt")! as? String







    return cell
}
return UITableViewCell()

}

} extension HistoryPTViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)

     let person = AirForceDatabase[indexPath.row]
    //Convert String to Double
    if let score = person.value(forKeyPath: "totalScore")! as? String, let doubleScore = Double(score) {

        officialTotalScore = doubleScore
        //officialTotalScore = Double(score)

        print("Score (officialTotalScore)")

    }
    var createdat :String!

    CompostiveLbl.text = "Composite Score:
(officialTotalScore)%"
    createdat = person.value(forKeyPath: "createdAt")! as? String
    print(createdat + "CREATED")
    if officialTotalScore >= 90 {
        print("Excellent")

        officialFinalScoreLbl.text = "Fitness Level:
 Excellent"
    }else if officialTotalScore >= 75 && officialTotalScore <= 89.9 {


        print("Composite Score: Satisfactory")
        officialFinalScoreLbl.text = "Fitness Level:
 Satisfactory"

    }else if  officialTotalScore <= 75 {

        print("Composite Score: Unsatisfactory")
        officialFinalScoreLbl.text = "Fitness Level:
  Unsatisfactory"
    }





    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = DateFormatter.Style.long
    dateFormatter.dateFormat = "yyyy-MM-dd"
    let convertedDate = dateFormatter.date(from: createdat)
    dateFormatter.dateFormat = "MMM dd yyyy"
    let date = dateFormatter.string(from: convertedDate!)

    NextPTLbl.text = "Test Date:
" + date
}


func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

       let person = AirForceDatabase[indexPath.row]
    if editingStyle == .delete {






   }


}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You should always use "NSFetchedResultsController" whenever tableview deals with the Core Data, because "NSFetchedResultsController" is built keeping tableView in mind.

It provides features which are useful for dealing with tableView

  1. Along with UITableViewDelegate & UITableviewdatasource protocols, adopt/conform to "NSFetchedResultsControllerDelegate" protocol.
  2. Then implement its 3 methods to delete the record from core data. And DON'T RELOAD the tableview. NSFetchedResultsController will take care of it.

for eg. let's load the data from core data (Entity name = Movie)

var fetchedResultsController: NSFetchedResultsController<Movie>

override func viewDidLoad()
{
    super.viewDidLoad()
    loadData()
}

func loadData() 
{
        fetchedResultController = getMovies(managedObjectContext: self.coreData.persistentContainer.viewContext)
        fetchedResultController.delegate = self
}


func getMovies(managedObjectContext: NSManagedObjectContext) -> NSFetchedResultsController<Movie> 
{
        let fetchedResultController: NSFetchedResultsController<Movie>

        let request: NSFetchRequest<Movie> = Movie.fetchRequest()
        let formatSort = NSSortDescriptor(key: "format", ascending: false)
        let nameSort = NSSortDescriptor(key: "title", ascending: true)
        request.sortDescriptors = [formatSort, nameSort]

        fetchedResultController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: managedObjectContext, sectionNameKeyPath: "format", cacheName: "MyMovieLibrary")

        do
        {
            try fetchedResultController.performFetch()
        }
        catch
        {
            fatalError("Error in fetching records")
        }

        return fetchedResultController
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int
{
    if let sections = fetchedResultController.sections
    {
        return sections.count
    }
    return 0
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    if let sections = fetchedResultController.sections
    {
        let currentSection = sections[section]
        return currentSection.numberOfObjects
    }
    return 0
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "movieCell", for: indexPath) as! MovieTableViewCell

    let movie = fetchedResultController.object(at: indexPath)
    cell.configureCell(movie: movie)

    return cell
}

Delete a record from core data

// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
    let managedObjectContext = coreData.persistentContainer.viewContext

    if editingStyle == .delete
    {
        movieToDelete = fetchedResultController.object(at: indexPath)

        let confirmDeleteAlertController = UIAlertController(title: "Remove Movie", message: "Are you sure you would like to delete "(movieToDelete!.title!)" from your movie library?", preferredStyle: UIAlertControllerStyle.actionSheet)

        let deleteAction = UIAlertAction(title: "Delete", style: UIAlertActionStyle.default, handler: { [weak self] (action: UIAlertAction) -> Void in
            managedObjectContext.delete((self?.movieToDelete!)!)
            self?.coreData.saveContext()
            self?.movieToDelete = nil
        })

        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { [weak self] (action: UIAlertAction) -> Void in
            self?.movieToDelete = nil
        })

        confirmDeleteAlertController.addAction(deleteAction)
        confirmDeleteAlertController.addAction(cancelAction)

        present(confirmDeleteAlertController, animated: true, completion: nil)

    }
}

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 NSFetchedResultsChangeType.delete:
        print("NSFetchedResultsChangeType.Delete detected")
        if let deleteIndexPath = indexPath
        {
            tableView.deleteRows(at: [deleteIndexPath], with: UITableViewRowAnimation.fade)
        }
    case NSFetchedResultsChangeType.insert:
        print("NSFetchedResultsChangeType.Insert detected")
    case NSFetchedResultsChangeType.move:
        print("NSFetchedResultsChangeType.Move detected")
    case NSFetchedResultsChangeType.update:
        print("NSFetchedResultsChangeType.Update detected")
        tableView.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.fade)
    }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
    tableView.endUpdates()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...