在超类中声明ivars或在子类中声明@synthesize?

时间:2013-08-06 14:44:32

标签: objective-c properties subclass

当我在超类中声明@property而没有声明ivars时,将其子类化并尝试使用子类中的超类ivar(_propertyName)实现getter,xcode调用一个错误,指出{{1} }。

符合最佳编程实践的解决方案是什么?

我应该在Use of undeclared identifier '_propertyName'的子类或

@synthesize propertyName = _propertyName
@implementation

修改
我确实理解了属性的访问器方法的自动“综合”以及编译器创建的“underbar ivars” 可以通过接口或实现部分中@interface SuperClass : AnotherClass { Type *_propertyName; } @property Type *propertyName; @end 的实现来访问ivar,而无需任何SuperClass或ivars声明。

进一步澄清我的案件: 免责声明:内容被窃取的代码块来自Alfie Hanssen

@synthesize

5 个答案:

答案 0 :(得分:7)

如果要在超类和子类中都使用ivar,则必须在超类的接口中声明它,因为它是两个实现中包含的唯一文件。否则,你只是想猜测超类的实现可能会发生什么,xcode不会玩游戏。

以上是否存在使用该ivar的属性。

现在,如果您在超类中有一个属性,并且您在子类实现中写入:

@synthesize propertyName = _propertyName

你只是说你放弃了超类中该属性的任何实现,你想要xcode生成的标准setter和getter,在一个名为_propertyname的ivar上工作。也许超类的工作方式相同,也许不是。

答案 1 :(得分:0)

这应该可以正常工作。 self.tableView_tableView都应该可以从SubViewController访问。

@interface SuperViewController : UIViewController
@property (nonatomic, strong) UITableView * tableView; // ivar _tableView is automatically @synthesized
@end

#import "SuperViewController.h"

@interface SubViewController : SuperViewController
// Empty
@end

@implementation SubViewController

- (void)viewDidLoad
{
    NSLog(@"tableView: %@", self.tableView);
}

@end

修改 好的,现在我明白你的问题更好了。看看这个question。似乎是重复的,似乎它回答了你的问题。即看起来你必须明确定义实例变量。

答案 2 :(得分:0)

显然,ivar的自动合成在这种情况下不起作用。以下代码因编译器错误“使用未声明的标识符_x”而失败,但仅适用于JFNBclass。取消注释ivar声明,编译器错误就消失了。默认合成似乎不会创建继承类可见的_x。

JFNAclass.h

#import <Foundation/Foundation.h>

@interface JFNAclass : NSObject {
  // NSNumber *_x;
}

@property NSNumber *x;
- (NSNumber *) xTest;

@end

JFNAclass.m

#import "JFNAclass.h"

@implementation JFNAclass

- (NSNumber *) xTest
{
  return _x;
}

@end

JFNBclass.h

#import <Foundation/Foundation.h>
#import "JFNAclass.h"

@interface JFNBclass : JFNAclass

- (void) printIt;
- (void) setIt;

@end

JFNBclass.m

#import "JFNBclass.h"

@implementation JFNBclass

- (void) setIt
{
    _x = [[NSNumber alloc] initWithInt:2];
}

- (void) printIt
{
  NSLog(@"_x is %@", _x);
}

@end

答案 3 :(得分:0)

@synthesize创建的Ivars为@private。 (对于显式@synthesize语句和自动综合,都是如此。)

您的班级SuperViewController确实有一个ivar _tableView,但它是@private,因此您的子类无法使用它。如果你需要一个子类可以使用的ivar,你需要明确地声明ivar并使其成为@private之外的其他东西。 (您还想使用@synthesize tableView=_tableView,因此该属性使用您声明的ivar。)

答案 4 :(得分:0)

我根本不会访问ivar。您想要覆盖getter,所以只需致电super

- (UITableView *)tableView {
    UITableView *tableView = [super tableView];
    if ( ! tableView) {
        tableView = [[SubclassOfUITableView alloc] init];
        self.tableView = tableView;
    }
    return tableView;
}