5

当我只@property在超类中声明 a 而不声明 ivars 时,将其子类化并尝试_propertyName在子类中使用超类 ivar() 实现 getter,xcode 调用错误声明Use of undeclared identifier '_propertyName'

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

我应该@synthesize propertyName = _propertyName@implementation子类中还是

@interface SuperClass : AnotherClass
{
    Type *_propertyName;
}

@property Type *propertyName;

@end

编辑:
我确实了解属性访问器方法的自动“综合”以及编译器创建“下划线 ivars”。
ivar 可以从接口或实现部分中SuperClass没有任何@synthesize 或声明的 ivars 的实现中访问。

进一步澄清我的情况:免责声明:内容从 Alfie Hanssen 窃取的代码块

@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); // this is perfectly OK
}

// ************* This causes problem **************
- (UITableView *) tableView {
    if (!_tableView) {    // Xcode error: Use of undeclared identifier '_propertyName'
        _tableView = [[SubclassOfUITableView alloc] init];
    }
    return _tableView;
}
// ************************************************


@end
4

5 回答 5

7

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

无论是否存在使用该 ivar 的属性,上述情况都是正确的。

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

@synthesize propertyName = _propertyName

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

于 2013-08-06T17:01:11.943 回答
0

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

您的班级SuperViewController确实有一个 ivar _tableView,但是@private您的子班级不能使用它。如果您需要子类可以使用的 ivar,则需要显式声明该 ivar 并将其设为@private. (您还想使用@synthesize tableView=_tableView,因此该属性使用您声明的 ivar。)

于 2013-08-06T19:32:44.203 回答
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

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

于 2013-08-06T14:59:49.973 回答
0

我根本不会访问 ivar。你想覆盖 getter,所以只需调用super.

- (UITableView *)tableView {
    UITableView *tableView = [super tableView];
    if ( ! tableView) {
        tableView = [[SubclassOfUITableView alloc] init];
        self.tableView = tableView;
    }
    return tableView;
}
于 2013-08-06T19:53:57.383 回答
0

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

JFNA类.h

#import <Foundation/Foundation.h>

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

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

@end

JFNA类.m

#import "JFNAclass.h"

@implementation JFNAclass

- (NSNumber *) xTest
{
  return _x;
}

@end

JFNB类.h

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

@interface JFNBclass : JFNAclass

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

@end

JFNB类.m

#import "JFNBclass.h"

@implementation JFNBclass

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

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

@end
于 2013-08-06T18:15:35.733 回答