【问题标题】:Getting around having to @synthesize when changing accessor methods in subclasses在更改子类中的访问器方法时不必@synthesize
【发布时间】:2013-12-01 00:30:18
【问题描述】:

我有几个 UITableViewControllers 并且希望它们都有几个属性,比如 fetchedResultsController 和 managedObjectContext。所以我为所有这些创建了一个抽象类,这样我就可以一次添加这些公共属性,并符合一些协议(例如和我遇到的其他协议)并为所有这些类似的 TVC 更改/添加任何代码。我在这个抽象类的头文件中定义了一个名为 fetchedResultsController 的属性:

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

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

@synthesize fetchedResultsController = _fetchedResultsController;

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

我的问题:

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

或者换句话说:

有没有办法为在超类中定义的属性创建自定义访问器方法,而不必@synthesize iVar?

【问题讨论】:

    标签: ios objective-c inheritance accessor


    【解决方案1】:

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

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

    子类.m

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

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

    如果您的子类也覆盖了 setter,您可能希望在调用 setFetchedResultsController: 时调用 self 而不是 super

    【讨论】:

    • 感谢@rmaddy 的快速回复。不错,很简单。为什么你在这一行叫'super'而不是self:'NSFetchedResultsController *result = [super fetchedResultsController]'?
    • 啊,愚蠢的问题。我想你会打电话给super,因为如果你打电话给self,如果没有设置fetchedResultsController,它只会循环。所以我想我关于这个答案的问题变成了,你为什么或者你会怎么打电话给NSFecthedResultsController *result = [self fetchedResultsController],就像你在底部提到的那样?感谢您的帮助!
    • 正确 - 调用 self fetchedResultsController 会导致无限递归。调用 super fetchedResultsController 从您在父类中无权访问的 ivar 获取值。在底部,我说的是setFetchedResultsController:,而不是fetchedResultsController
    【解决方案2】:

    正如其他答案所说,您的子类无法访问其父级的私有 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

    【讨论】:

      猜你喜欢
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      相关资源
      最近更新 更多