在子类中更改访问器方法时,必须绕过@synthesize

时间:2013-12-01 00:30:18

标签: ios objective-c inheritance accessor

我有几个UITableViewControllers,并希望它们都有几个属性,如fetchedResultsController和managedObjectContext。所以我为所有这些做了一个抽象类,这样我就可以添加这些常用属性,并符合某些协议(例如我遇到的其他协议),并为所有这些类似的TVC更改/添加任何代码。我在这个抽象类的标题中定义了一个名为fetchedResultsController的属性:

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

在我的抽象类的每个子类中,我想为这个属性创建一个自定义的getter,以便懒惰地实例化fetchedResultsController并初始化获取请求等。我发现我必须添加:

@synthesize fetchedResultsController = _fetchedResultsController;

让每个子类都有一个iVar来制作getter。

我的问题:

为什么我在抽象类的每个子类中都看不到属性的iVars?

或换句话说:

有没有办法为超类中定义的属性创建自定义访问器方法而不必对@Vnthesize进行iVar?

2 个答案:

答案 0 :(得分:2)

ivars是定义属性的类的私有(并合成了ivar)。子类无权访问其父类的私有ivars。这是件好事。

为什么不在你的子类中这样的东西(而不是让每个子类调用@synthesize):

Subclass.m

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

    return result;
}

现在不需要子类访问父类的私有ivar。

如果您的子类也覆盖了设置者,则可能需要在调用self时呼叫super而不是setFetchedResultsController:

答案 1 :(得分:0)

正如其他答案所说,您的子类无法访问其父级的私有iVar,您应该感谢。您的问题的解决方案非常简单和优雅。

@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

使用此样式实现,每个子类只需实现-createFetchedResultsController