开发者

Subclassing with CoreData and UITableviewController

I'm trying to subclass UITableViewController to minimize my code.

Basically I have all code in the super class exempt for the FetchedResultController, which I override in my subclasses.

It worked without this "split" but now it returns an EXC_BAD_ACCESS message.

Here is the code in my subclass:

    - (NSFetchedResultsController *)fetchedResultsController
    {
        if (super.fetchedResultsController != nil)
        {
            return super.fetchedResultsController;
        }
        id delegate = [[UIApplication sharedApplication] delegate];

        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Question" inManagedObjectContext:[delegate managedObjectContext]];
        [fetchRequest setEntity:entity];

        [fetchRequest setFetchBatchSize:20];

        NSSortDescriptor*sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"up_vote_count" ascending:YES];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];

        //next line returns EXC_BAD_ACCESS
        NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[delegate manag开发者_如何学CedObjectContext] sectionNameKeyPath:nil cacheName:@"Root2"];
        aFetchedResultsController.delegate = self;
        super.fetchedResultsController = aFetchedResultsController;

        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error])
        {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }

        return super.fetchedResultsController;
    }   

I'm curious if I should use super. or self. but self. crashed in the if statement.

-- EDIT --

Here is the @interface of the superclass. My subclass doesn't contain anything except of the overwritten methods.

@interface CoreDataTableView : UITableViewController <NSFetchedResultsControllerDelegate> {  


 }

 - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;

 @property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
 @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
 @end


self. crashed in the if statement

That is because you're recursively calling the fetchedResultsController method into an infinite loop.

Now, there are a few other problems.

First, I would suggest splitting that method into 2 parts:

  1. initializing the fetched results controller
  2. fetching the data

Also, your fetchRequest is never released. Nor is aFetchedResultsController. You own both of these objects inside that method, so you must release them to prevent leaks.

Based on these remarks, here's how the code would look:

- (NSFetchedResultsController *)fetchedResultsController
{
    // In this method, because it's overriding the accessor in the super-class,
    // you must use |super.fetchedResultsController|, 
    // otherwise you will trigger an infinite loop!

    if (super.fetchedResultsController != nil)
    {
        return super.fetchedResultsController;
    }
    id delegate = [[UIApplication sharedApplication] delegate];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // ...

    // omitted the other details...       

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[delegate managedObjectContext] sectionNameKeyPath:nil cacheName:@"Root2"];
    aFetchedResultsController.delegate = self;
    super.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];

    return super.fetchedResultsController;
}


- (void)fetch
{
    NSError *error = nil;
    // using |self| here is OK, because you're referring to the current object's method
    if (![self.fetchedResultsController performFetch:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }        
} 

As for using super vs self:

  • super.foo or [super foo] starts to look for method foo in the super-class
  • self.foo or [self foo] looks for method foo in the current object's class

In your case, it wouldn't make much difference except for the fact that self.fetchedResultsController would trigger an infinite loop as I mentioned before, if used inside the accessor.

I hope I got this right and that it cleared things up for you...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜