2015-08-20 2 views
0

Это код:UITableView грохот при удалении строки с CoreData

import UIKit 
import CoreData 

class ExerciseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPickerViewDataSource, UIPickerViewDelegate, NSFetchedResultsControllerDelegate { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     VDL() 

     //sets stepper configs 
     setsStepper.wraps = false 
     setsStepper.autorepeat = true 
     setsStepper.continuous = true 
     setsStepper.tintColor = UIColor.redColor() 
     setsStepper.minimumValue = 0 
     setsStepper.maximumValue = 500 
     setsStepper.value = 0 

     //reps stepper configs 
     repsStepper.wraps = false 
     repsStepper.autorepeat = true 
     repsStepper.continuous = true 
     repsStepper.tintColor = UIColor.orangeColor() 
     repsStepper.minimumValue = 0 
     repsStepper.maximumValue = 500 
     repsStepper.value = 0 

     exerciseTableView.reloadData() 
    } 

    var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext 
    var fetchedResultsController: NSFetchedResultsController? 

    @IBOutlet var exerciseTableView: UITableView! 

    @IBOutlet var daysPickerView: UIPickerView! 

    @IBOutlet var exerciseName: UITextField! 
    @IBOutlet var setsStepper: UIStepper! 
    @IBOutlet var repsStepper: UIStepper! 

    @IBOutlet var setsNumber: UILabel! 
    @IBOutlet var repsNumber: UILabel! 

    var daysArray = [TrainingDay]() 
    var detailsArray = [TrainingDetails]() 

    func VDL() { 
     let fetchRequest = NSFetchRequest(entityName: "TrainingDay") 
     let sort = NSSortDescriptor(key: "dayIndex", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     daysArray = (moc!.executeFetchRequest(fetchRequest, error: nil) as? [TrainingDay])! 
     if daysArray.count == 0 { // nothing there 
      let dayEntity = NSEntityDescription.entityForName("TrainingDay", inManagedObjectContext: moc!) 
      let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] 
      for (index, name) in enumerate(days) { 
       let newDay = TrainingDay(entity: dayEntity!, insertIntoManagedObjectContext: moc) 
       newDay.day = name 
       newDay.dayIndex = index 
       daysArray.append(newDay) 
       println("NAME: \(newDay.day) INDEX: \(newDay.dayIndex)") 
      } 
      var error: NSError? 
      moc!.save(&error) 
     } 
    } 


    func appendTrainingDetailsToArray() { 
     let row = daysPickerView.selectedRowInComponent(0) 
     let currentDay = daysArray[row] 

     let detailsEntity = NSEntityDescription.entityForName("TrainingDetails", inManagedObjectContext: moc!) 
     let trainingdetails = TrainingDetails(entity: detailsEntity!, insertIntoManagedObjectContext: moc) 
     trainingdetails.exerciseName = exerciseName.text 
     trainingdetails.repsNumber = repsNumber.text! 
     trainingdetails.setsNumber = setsNumber.text! 
     trainingdetails.trainingDay = currentDay 

     var error: NSError? 
     moc?.save(&error) 

     if let err = error { 
      var status = err.localizedFailureReason 
      println("\(status)") 
     } else { 
      println("CURRENT SETTING: \(trainingdetails.trainingDay)") 
     } 
    } 

    func fetchTrainingDetails() -> NSFetchRequest { 

     let fetchRequest = NSFetchRequest(entityName: "TrainingDetails") 
     fetchRequest.predicate = nil 
     let sortDescriptor = NSSortDescriptor(key: "trainingDay", ascending: true) 
     fetchRequest.sortDescriptors = [sortDescriptor] 
     fetchRequest.fetchBatchSize = 20 
     return fetchRequest 
    } 


    @IBAction func doneButton(sender: AnyObject) { 
     appendTrainingDetailsToArray() 
     fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchTrainingDetails(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil) 
     fetchedResultsController?.delegate = self 
     fetchedResultsController?.performFetch(nil) 
     exerciseTableView.reloadData() 
    } 

    @IBAction func setsStepperAction(sender: UIStepper) { 
     println("\(Int(sender.value))") 
     setsNumber.text = Int(sender.value).description 
    } 

    @IBAction func repsStepper(sender: UIStepper) { 
     println("\(Int(sender.value))") 
     repsNumber.text = Int(sender.value).description 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return fetchedResultsController?.sections?[section].numberOfObjects ?? 0 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let cell = tableView.dequeueReusableCellWithIdentifier("exerciseCell", forIndexPath: indexPath) as! UITableViewCell 
     let details = fetchedResultsController!.objectAtIndexPath(indexPath) as! TrainingDetails 
     cell.textLabel!.text = "\(details.exerciseName)" 
     cell.detailTextLabel!.text = "Sets: #\(details.setsNumber) Reps: #\(details.repsNumber)" 

     return cell 
    } 

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 
     return true 
    } 

    func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle { 
     return UITableViewCellEditingStyle.Delete 
    } 

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
     println("section and row \(indexPath.section) \(indexPath.row) ") 
     if (editingStyle == UITableViewCellEditingStyle.Delete) { 
      let detailsForRow : NSManagedObject = fetchedResultsController!.objectAtIndexPath(indexPath) as! TrainingDetails 
      moc?.deleteObject(detailsForRow) 
      moc?.save(nil) 
      exerciseTableView.beginUpdates() 
      exerciseTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      exerciseTableView.endUpdates() 
     } 
    } 

    //PICKER VIEW DELEGATE AND DATASOURCE METHODS 
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { 
     return 1 
    } 

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     return daysArray.count 
    } 

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { 
      let trainingDay = daysArray[row] 
      return trainingDay.day 
    } 

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 

     let currentDay = daysArray[row] 
     let fetchRequest = NSFetchRequest(entityName: "TrainingDetails") 
     let predicate = NSPredicate(format: "trainingDay = %@", currentDay) 
     fetchRequest.predicate = predicate 
     let sort = NSSortDescriptor(key: "exerciseName", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     detailsArray = (moc!.executeFetchRequest(fetchRequest, error: nil) as? [TrainingDetails])! 
     exerciseTableView.reloadData() 

    } 

    // MARK: NSFetchedResultsControllerDelegate 
    func controllerWillChangeContent(controller: NSFetchedResultsController) { 
     self.exerciseTableView.beginUpdates() 
    } 
    func controller(controller: NSFetchedResultsController, 
     didChangeObject anObject: AnyObject, 
     atIndexPath indexPath: NSIndexPath?, 
     forChangeType type: NSFetchedResultsChangeType, 
     newIndexPath: NSIndexPath?) 
    { 
     switch type { 
     case NSFetchedResultsChangeType.Insert: 
      // Note that for Insert, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Delete: 
      // Note that for Delete, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Update: 
      // Note that for Update, we update the row at __indexPath__ 
      if let updateIndexPath = indexPath { 
       let cell = self.exerciseTableView.cellForRowAtIndexPath(updateIndexPath) 
       let details = self.fetchedResultsController!.objectAtIndexPath(updateIndexPath) as? TrainingDetails 

       cell!.textLabel!.text = "\(details!.exerciseName)" 
       cell!.detailTextLabel!.text = "Sets: #\(details!.setsNumber) Reps: #\(details!.repsNumber)" 
      } 
     case NSFetchedResultsChangeType.Move: 
      // Note that for Move, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 

      // Note that for Move, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     } } 

    func controller(controller: NSFetchedResultsController, 
     didChangeSection sectionInfo: NSFetchedResultsSectionInfo, 
     atIndex sectionIndex: Int, 
     forChangeType type: NSFetchedResultsChangeType) 
    { 
     switch type { 
     case .Insert: 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.exerciseTableView.insertSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
     case .Delete: 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.exerciseTableView.deleteSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
     default: 
      "" 
     } 
    } 
    func controllerDidChangeContent(controller: NSFetchedResultsController) { 
     exerciseTableView.endUpdates() 
    } 
} 

Всякий раз, когда я пытаюсь удалить строку из Tableview, приложение аварий. Я читал что-то о numberOfRowInSection, вызываемом внутри commingEditingStyle. У кого-нибудь есть идея?

Я пробовал много разных способов стереть его, но он не пойдет.

UPDATE

Ну, я сделал это так:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
     println("section and row \(indexPath.section) \(indexPath.row) ") 
     if self.fetchedResultsController == nil { 
      println("error when trying to delete object from managed object") 

     } else if (editingStyle == UITableViewCellEditingStyle.Delete) { 
      moc?.deleteObject(detailsArray[indexPath.row] as NSManagedObject) 
      detailsArray.removeAtIndex(indexPath.row) 

      var error: NSError? 
      moc?.save(&error) 
     } 
    } 

Теперь, когда я пытаюсь удалить что-то он работает нормально, но только если это первый элемент в виде таблицы. Если я попытаюсь удалить что-то в середине представления таблицы, приложение вылетает с фатальной ошибкой: Индекс массива выходит за пределы диапазона

Также, как это сделать в Swift?

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (self.fetchedResultsController == nil) { 
    } else { 
     // Do stuff 
     if (editingStyle == UITableViewCellEditingStyleDelete) { 
      NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 
      [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; 

      NSError *error = nil; 
      if (![context save:&error]) { 
       // Replace this implementation with code to handle the error appropriately. 
       // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       //abort(); 
      } 
     } 
    } 
} 

Спасибо!

+0

Crash - это индекс массива за пределами границ? Показать сообщение об ошибке. Где вы устанавливаете количество разделов? – Wain

+0

Не пытайтесь удалять что-либо из таблицыView - используйте NSFetchedResultsController и методы NSFetchedResultsControllerDelegate для представления записей данных кода в UITableView. Все, что вы делаете, это удалить объект из Core Data, и UITableView будет волшебным образом обновлять себя, аналогично, когда вы создаете новый объект Core Data, он также волшебным образом появится в UITableView. https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsController_Class/#//apple_ref/doc/uid/TP40008227-CH1-SW23 –

ответ

1

Вашего объектный код C преобразуется в Swift

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
if self.fetchedResultsController == nil { 

} 
else { 
    if editingStyle == UITableViewCellEditingStyleDelete { 
     var context: NSManagedObjectContext = self.fetchedResultsController.managedObjectContext() 
     context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath)) 
     var error: NSError? = nil 
     if !context.save(&error) { 
      NSLog("Unresolved error %@, %@", error, error.userInfo()) 
     } 
    } 
    } 
} 

Вот Link преобразовать объектный код C Свифт

Надеется, что это будет полезно.

+0

Спасибо вам большое !!! –

1

В дополнение к моему комментарию выше приведен пример UITableView, в котором используется NSFetchedResultsController.

Код ниже содержит код для добавления и удаления объектов Core Data, так что UITableView автоматически обновит себя, чтобы показать/удалить соответствующие объекты.

Вы можете скачать полный пример приложение здесь http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/

// 
// MasterViewController.m 
// CoreDataLibraryApp 
// 
// 

#import "CompanyViewController.h" 
#import "OSCDStackManager.h" 
#import "CompanyDetailViewController.h" 

@interface CompanyViewController() 
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath; 
@end 

@implementation CompanyViewController 

- (void)awakeFromNib 
{ 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 
     self.clearsSelectionOnViewWillAppear = NO; 
     self.preferredContentSize = CGSizeMake(320.0, 600.0); 
    } 
    [super awakeFromNib]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    //self.navigationItem.leftBarButtonItem = self.editButtonItem; 
    self.navigationItem.leftItemsSupplementBackButton = YES; 
    [self.navigationItem setHidesBackButton:NO]; 
    // Uncomment the following line to preserve selection between presentations. 
    self.clearsSelectionOnViewWillAppear = NO; 

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 
    // self.navigationItem.rightBarButtonItem = self.editButtonItem; 


    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)]; 
    self.navigationItem.rightBarButtonItem = addButton; 
    //self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(storeChanged) name:OSStoreChangeNotification 
               object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshUI) name:OSDataUpdatedNotification 
               object:nil]; 

    UIRefreshControl *refresh = [[UIRefreshControl alloc] init]; 

    refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Load"]; 

    [refresh addTarget:self action:@selector(refresh) 

     forControlEvents:UIControlEventValueChanged]; 

    self.managedObjectContext = [[OSCDStackManager sharedManager] managedObjectContext]; 
    FLOG(@"managedObjectContext is %@",self.managedObjectContext); 
    [self fetchedResultsController]; 
    self.detailViewController.detailItem = nil; 
} 
- (void)stopRefresh { 

    [self.refreshControl endRefreshing]; 

} 
- (void)refresh { 
    FLOG(@"refresh called"); 
    [[OSCDStackManager sharedManager] loadDataInBackground]; 
    [self performSelector:@selector(stopRefresh) withObject:nil afterDelay:0.5]; 
} 
-(void)storeChanged { 
    FLOG(@"storeChanged called"); 
    _fetchedResultsController = nil; 
    self.managedObjectContext = [[OSCDStackManager sharedManager] managedObjectContext]; 
    FLOG(@"managedObjectContext is %@",self.managedObjectContext); 
    [self fetchedResultsController]; 
    self.detailViewController.detailItem = nil; 
    [[self tableView] reloadData]; 
} 
-(void)refreshUI { 
    FLOG(@"refreshUI called"); 

    /* 
    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) { 
    // Replace this implementation with code to handle the error appropriately. 
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    //abort(); 
    } 
    */ 
    [[self tableView] reloadData]; 
} 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)insertNewObject:(id)sender 
{ 
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; 
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; 

    NSString *str = ([[OSCDStackManager sharedManager] isCloudEnabled] ? @"New Company(c)" : @"New Company"); 
    // If appropriate, configure the new managed object. 
    // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template. 
    [newManagedObject setValue:str forKey:@"name"]; 

    // Save the context. 
    NSError *error = nil; 
    if (![context save:&error]) { 
     // Replace this implementation with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     //abort(); 
    } 
} 

#pragma mark - Table View 

// if fetchedResultsController == nil it means the database has not been initialised yet 
// and so we just return a single row saying "Loading, please wait..." 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    // return 1 section of fetechedResultsController == nil 
    if (self.fetchedResultsController == nil) 
     return 1; 
    else 
     return [[self.fetchedResultsController sections] count]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (self.fetchedResultsController == nil) { 

     return 1; 

    } else { 

     id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section]; 
     return [sectionInfo numberOfObjects]; 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 
    [self configureCell:cell atIndexPath:indexPath]; 
    return cell; 
} 

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (self.fetchedResultsController == nil) { 

     return NO; 

    } else { 
     // Return NO if you do not want the specified item to be editable. 
     return YES; 
    } 
} 

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (self.fetchedResultsController == nil) { 
    } else { 
     // Do stuff 
     if (editingStyle == UITableViewCellEditingStyleDelete) { 
      NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 
      [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; 

      NSError *error = nil; 
      if (![context save:&error]) { 
       // Replace this implementation with code to handle the error appropriately. 
       // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       //abort(); 
      } 
     } 
    } 
} 

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // The table view should not be re-orderable. 
    return NO; 
} 
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

    // Don't allow user to select a row if Core Data stack is not set up yet. 
    if (self.fetchedResultsController == nil) { 
     NSLog(@" fetchedResultsController == nil"); 
     return nil; 
    } 
    // By default, allow row to be selected 
    return indexPath; 
} 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    FLOG(@" called"); 

    if (self.fetchedResultsController == nil) { 
     FLOG(@" fetchedResultsController == nil"); 

    } else { 
     FLOG(@" fetchedResultsController != nil"); 

      CompanyViewController *newTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"CompanyMenuTableViewController"]; 
      newTableViewController.detailItem = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
      [self.navigationController pushViewController:newTableViewController animated:YES]; 

    } 
} 
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { 
    FLOG(@" called"); 

    if (self.fetchedResultsController == nil) { 
     FLOG(@" fetchedResultsController == nil"); 

    } else { 
     FLOG(@" fetchedResultsController != nil"); 
     // if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 


      if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 

       // Create and configure a new detail view controller appropriate for the selection. 
       self.detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"CompanyDetailViewController"]; 
       NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
       self.detailViewController.detailItem = object; 
       //self.detailViewController.title = [object valueForKey:@"name"]; 

       [self.navigationController pushViewController:self.detailViewController animated:YES]; 
      } else { 
       // We want to highlight the selected row 
       [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; 

       FLOG(@" Device is iPad"); 
       DetailViewManager *detailViewManager = (DetailViewManager*)self.splitViewController.delegate; 
       FLOG(@" detailViewManager is %@", detailViewManager); 

       // Create and configure a new detail view controller appropriate for the selection. 
       self.detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"CompanyDetailViewController"]; 
       NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
       self.detailViewController.detailItem = object; 
       //self.detailViewController.title = [object valueForKey:@"name"]; 

       detailViewManager.detailViewController = self.detailViewController; 
      } 
     // } 
    } 
} 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"showCompanyDetail"]) { 
     NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
     NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
     [[segue destinationViewController] setDetailItem:object]; 
    } 
} 

#pragma mark - Fetched results controller 

- (NSFetchedResultsController *)fetchedResultsController 
{ 
    if (_fetchedResultsController != nil) { 
     return _fetchedResultsController; 
    } 

    if (self.managedObjectContext == nil) return nil; 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Company" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
    NSArray *sortDescriptors = @[sortDescriptor]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 

    // Edit the section name key path and cache name if appropriate. 
    // nil for section name key path means "no sections". 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) { 
     // Replace this implementation with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 

    } 

    return _fetchedResultsController; 
} 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
{ 
    NSLog(@"controllerWillChangeContent called"); 
    [self.tableView beginUpdates]; 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type 
{ 
    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    UITableView *tableView = self.tableView; 

    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeUpdate: 
      [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
      break; 

     case NSFetchedResultsChangeMove: 
      [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    NSLog(@"controllerDidChangeContent called"); 
    [self.tableView endUpdates]; 
} 

/* 
// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed. 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
// In the simplest, most efficient, case, reload the table view. 
[self.tableView reloadData]; 
} 
*/ 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{ 
    if (self.fetchedResultsController == nil) { 
     cell.textLabel.text = @"Loading please wait..."; 
     cell.accessoryType = UITableViewCellAccessoryNone; 
     UIActivityIndicatorView *progressView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
     cell.accessoryView = progressView; 
     [progressView startAnimating]; 

    } else { 
     cell.accessoryView = nil; 
     NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
     cell.textLabel.text = [[object valueForKey:@"name"] description]; 
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
     cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 
    } 
} 

@end 
Смежные вопросы