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和属性isreadwrite
-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;
}