Question

I've got several UITableViewControllers and want all of them to have several properties like a fetchedResultsController and a managedObjectContext. So I've made an abstract class for all of them so that I can add these common properties once, as well as conform to some protocols ( for example and others I come across) and change/add any code for all these similar TVCs. I've defined a property called fetchedResultsController in the header of this abstract class:

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

In each subclass of my abstract class, I want to create a custom getter for this property to instantiate the fetchedResultsController lazily and initialise the fetch request etc. I'm finding that I have to add:

@synthesize fetchedResultsController = _fetchedResultsController;

To every single subclass to have an iVar to make the getter.

My question:

Why can't I see the iVars of properties in each of my subclasses of my abstract class?

Or in other words:

Is there a way to make custom accessor methods for a property that's defined in a superclass without having to @synthesize the iVar?

Was it helpful?

Solution

The ivars are private to the class that defines the property (and synthesizes the ivar). Subclasses don't have access to private ivars of their parent classes. That's a good thing.

Why don't you so something like this in your subclass (instead of having each subclass call @synthesize):

Subclass.m

- (NSFetchedResultsController *)fetchedResultsController {
    NSFetchedResultsController *result = [super fetchedResultsController];
    if (!result) {
        result = ... // lazy load your controller
        [super setFetchedResultsController:result];
    }

    return result;
}

Now there is no need for the subclass to access the private ivar of the parent class.

If your subclass also overrides the setter, you may want to call self instead of super on the call to setFetchedResultsController:.

OTHER TIPS

As other answers have said, your subclasses cannot access the private iVar of their parent and you should be thankful for that. The solution to your problem is very simple and elegant.

@interface BaseTableViewController : UITableViewController
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
- (BOOL)isFetchedResultsControllerLoaded;
- (NSFetchedResultsController *)createFetchedResultsController;
@end

@implementation BaseTableViewController

- (BOOL)isFetchedResultsControllerLoaded
{
    return (_fetchedResultsController!=nil);
}

- (NSFetchedResultsController *)createFetchedResultsController
{
    [self doesNotRecognizeSelector:_cmd];
    return nil;  // To please the static analyzer
}

- (NSFetchedResultsController *)fetchedResultsController
{
    if (!_fetchedResultsController) {
        _fetchedResultsController = [self createFetchedResultsController];
        NSAssert(_fetchedResultsController!=nil, @"Creating Fetched Results Controller failed.");
        // Do any common initialization, like setting a delegate
    }
    return _fetchedResultsController;
}

@end

With this style implementation, each of your subclasses only has to implement -createFetchedResultsController.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top