Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在超类中声明IVAR还是在子类中声明@synthesis?_Objective C_Properties_Subclass - Fatal编程技术网

Objective c 在超类中声明IVAR还是在子类中声明@synthesis?

Objective c 在超类中声明IVAR还是在子类中声明@synthesis?,objective-c,properties,subclass,Objective C,Properties,Subclass,当我在一个超类中声明一个@property而不声明ivar时,将其子类化并尝试使用子类中的超类ivar(\u propertyName)实现getter,xcode调用一个错误,声明使用未声明的标识符'\u propertyName' 符合最佳编程实践的解决方案是什么 我应该在子类的@implementation中合成propertyName=\u propertyName,还是 @interface SuperClass : AnotherClass { Type *_property

当我在一个超类中声明一个
@property
而不声明ivar时,将其子类化并尝试使用子类中的超类ivar(
\u propertyName
)实现getter,xcode调用一个错误,声明
使用未声明的标识符'\u propertyName'

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

我应该在子类的
@implementation
中合成propertyName=\u propertyName,还是

@interface SuperClass : AnotherClass
{
    Type *_propertyName;
}

@property Type *propertyName;

@end
编辑:
我确实了解属性的访问器方法的自动“合成”以及编译器创建的“underbar IVAR”。
可以通过
超类的实现访问ivar,而无需在接口或实现部分中进行任何
@synthesis
或ivar声明

进一步澄清我的案件: 免责声明:内容从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

这应该很好用
self.tableView
\u tableView
都应该可以从
子视图控制器
访问

@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
编辑:
好吧,现在我明白你的问题更好了。看看这个。看起来像是复制品,似乎回答了你的问题。也就是说,看起来您必须显式定义实例变量

如果希望在超类和子类中都使用ivar,则必须在超类的接口中声明它,因为它是两种实现中都包含的唯一文件。否则,您只是想猜测在超类的实现中会出现什么,而xcode不会玩游戏

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

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

@synthesize propertyName = _propertyName

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

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

JFNAclass.h

#import <Foundation/Foundation.h>

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

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

@end
JFNBclass.h

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

@interface JFNBclass : JFNAclass

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

@end

@synthetic
创建的IVAR是
@private
。(显式
@synthesis
语句和自动合成都是如此。)


您的类
SuperViewController
确实有一个ivar
\u tableView
,但它是
@private
,因此您的子类无法使用它。如果需要子类可以使用的ivar,则需要显式声明该ivar,并将其设置为非
@private
。(您还需要使用
@synthesis tableView=\u tableView
以便属性使用您声明的ivar。)

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

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

这很奇怪:在Objective C中,IVAR在默认情况下是受保护的,所以您的子类应该能够访问它们,就好像它们是自己的一样。如何访问
\u propertyName
以获取该错误?如果您的属性是
@property Type*\u propertyName
那么我认为ivar应该是
\uuuuPropertyName
。(两个下划线)为什么您的子类需要直接访问ivar?仅供参考,不再需要
@synthesis
属性;只需在头文件中声明它们,合成就会由Xcode/编译器自动完成。对不起,我更正了输入错误。ivar是自动创建的,但它只能由超类直接访问。@BergQuester我正在使用超类中的ivar来存储一个对象,该对象在子类的实现中是该对象的子类。好的,如果我将此方法添加到SubViewController实现:-(UITableView*)tableView{if(!\u tableView){{u tableView=[[subassofuitableview alloc]init];}返回{u tableView;}“ivar\u tableView自动\@合成”你怎么知道的?你假设m文件中没有\@synthesis,也没有getter或setter的自定义实现。你怎么知道?这不是问题的重复,因为情况正好相反。我想要ivar,我不必合成它,因为超类只实现setter和属性is
readwrite
-ivar很容易从超类的实现中访问。我没有运行那个测试……结果与您引用的答案完全一致。Quelle惊讶!所以我对这个答案投了更高的票。很高兴您花时间写下了这个,我写下了几乎相同的代码。但是如果您仔细阅读,我甚至在标题中说明了此解决方案。对不起,标题中的问号让我推断您对哪种技术有效有疑问。我可能应该提供更多代码。类似于我的案例
[super tableView]
将返回
(UITableView*)
alloc
ed和
init
ed)-不是
nil
-因此子类的getter(可能)永远不会返回
subassofuitableview
。不过,我根本不会访问ivar。如果两个getter都是惰性的,但它们返回不同的
UITableView
,那么创建方法
-(class)tableViewClass
覆盖了它。总有很好的解决方案。
#import "JFNBclass.h"

@implementation JFNBclass

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

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

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