My TableView содержит ячейки, представляющие журнал пробега. Мне нужно разрешить пользователям удалять любые ошибки. В таблице отображается список журналов в порядке убывания. Удаление верхней строки в порядке. При удалении любой другой строки мне нужно выпустить предупреждение в качестве предупреждения, и если оно подтверждено, удалите выбранную строку + все строки над ней. Это возможно? Есть ли какой-нибудь пример кода в любом месте?Swift UITableView удаляет выбранную строку и любые строки над ней
UPDATE
Исходя из двух ответов, которые я имел до сих пор я сделал следующее ....
import UIKit
import CoreData
class MileageLogsTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
@IBOutlet var milageLogTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
do {
try fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("Unable to fetch MileageLog")
print("\(fetchError), \(fetchError.localizedDescription)")
}
// Display an Edit button in the navigation bar for this view controller.
self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
// MARK: - Table view data source
private lazy var fetchedResultsController: NSFetchedResultsController = {
// Initialize Fetch Request
let fetchRequest = NSFetchRequest(entityName: "MileageLog")
// Add Sort Descriptors
let dateSort = NSSortDescriptor(key: "tripDate", ascending: false)
let mileSort = NSSortDescriptor(key: "startMileage", ascending: false)
fetchRequest.sortDescriptors = [dateSort, mileSort]
let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedObjectContext = delegate.managedObjectContext
// Initialize Fetched Results Controller
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: "rootCache")
//ADDED AS PER ANSWER FROM SANDEEP
fetchedResultsController.delegate = self
return fetchedResultsController
}()
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let sections = fetchedResultsController.sections {
return sections.count
}
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController.sections {
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MileageLogCell") as! MileageTableViewCell
// Fetch MileageLog
if let mileageLog = fetchedResultsController.objectAtIndexPath(indexPath) as? MileageLog {
//format date as medium style date
let formatter = NSDateFormatter()
formatter.dateStyle = .MediumStyle
let logDateString = formatter.stringFromDate(mileageLog.tripDate!)
//format NSNumber mileage to string
let mileageInt:NSNumber = mileageLog.startMileage!
let mileageString = String(mileageInt)
cell.lb_LogDate.text = logDateString
cell.lb_LogMileage.text = mileageString
cell.lb_LogStartLocation.text = mileageLog.startLocation
cell.lb_LogDestination.text = mileageLog.endLocation
}
return cell
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// MARK: Fetched Results Controller Delegate Methods
func controllerWillChangeContent(fetchedResultsController: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controllerDidChangeContent(fetchedResultsController: NSFetchedResultsController) {
tableView.endUpdates()
}
func controller(fetchedResultsController: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch (type) {
case .Insert:
break;
case .Delete:
let context = fetchedResultsController.managedObjectContext
if let indexPath = indexPath {
if indexPath.row == 0 {
//this is the top (first row)
// Deleting without warning
let objectToDelete = fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
context.deleteObject(objectToDelete)
do {
try context.save()
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} catch {
print(error)
}
self.tableView.reloadData();
} else {
//we are deleted a row that is not the top row
// we need to give a warning and if acknowledged then delele all rows from the selected row and all rows above it
let alertController = UIAlertController(title: nil, message: "Are you sure? This will remove this and all logs above it.", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
}
alertController.addAction(cancelAction)
let deleteAction = UIAlertAction(title: "Delete", style: .Default) { (action) in
for deleteindex in 0 ... indexPath.row {
let deleteIndexPath = NSIndexPath(forRow: deleteindex, inSection: 0)
let objectToDelete = self.fetchedResultsController.objectAtIndexPath(deleteIndexPath) as! NSManagedObject
context.deleteObject(objectToDelete)
do {
try context.save()
self.tableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: .Fade)
} catch {
print(error)
}
}
self.tableView.reloadData();
}
alertController.addAction(deleteAction)
// Dispatch on the main thread
dispatch_async(dispatch_get_main_queue()) {
self.presentViewController(alertController, animated: true, completion:nil)
}
}
}
break;
case .Update:
break;
case .Move:
break;
}
}
}
Теперь моя проблема заключается в том, что прикосновение Delete ничего не делает. Дерево правильно заполнено. Кнопка «Редактировать» находится на панели навигации. Нажмите «Изменить», и значок «нет записи» появится в каждой строке ... сдвиньте строку и появится блок «Удалить». Нажмите «Удалить» и ничего ...! Что я пропустил?
FINAL РАБОЧАЯ FIX
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
let context = fetchedResultsController.managedObjectContext
if indexPath.row == 0 {
//this is the top (first row)
// Deleting without warning
let indexPathToDelete = NSIndexPath(forRow: 0, inSection: 0)
let objectToDelete = fetchedResultsController.objectAtIndexPath(indexPathToDelete) as! NSManagedObject
context.deleteObject(objectToDelete)
do {
try context.save()
//self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} catch {
print(error)
}
//self.tableView.reloadData();
} else {
//we are deleted a row that is not the top row
// we need to give a warning and if acknowledged then delele all rows from the selected row and all rows above it
let alertController = UIAlertController(title: nil, message: "Are you sure? This will remove this and all logs above it.", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
}
alertController.addAction(cancelAction)
let deleteAction = UIAlertAction(title: "Delete", style: .Default) { (action) in
for deleteindex in 0 ... indexPath.row {
let deleteIndexPath = NSIndexPath(forRow: deleteindex, inSection: 0)
let objectToDelete = self.fetchedResultsController.objectAtIndexPath(deleteIndexPath) as! NSManagedObject
context.deleteObject(objectToDelete)
}
do {
try context.save()
} catch {
print(error)
}
}
alertController.addAction(deleteAction)
// Dispatch on the main thread
dispatch_async(dispatch_get_main_queue()) {
self.presentViewController(alertController, animated: true, completion:nil)
}
}
break;
default :
return
}
}
// MARK: Fetched Results Controller Delegate Methods
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
break;
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
break;
case .Move:
break;
}
}
Зачем вам нужен пример для этого приятеля ?? просто удалите строки из источника данных и перезагрузите tableview :) thats all :) –
Я новичок в iOS и быстро, поэтому мне может быть что-то не хватает ... TableView имеет кнопку редактирования на navbar. Пользователь нажимает на редактирование, затем выбирает строку и клики удаляет.Это приведет к удалению этой строки. Все до сих пор ... что мне нужно, это дополнение к этому, где код не только удалит выбранную строку, но и все строки над ней. – Mych
Вы не удаляете из uitableview, вы удаляете из источника данных, а затем вызываете tableView.reloadData(). – oyalhi