如果子类引用超类ivar,则合成不相关的属性将失败

eri*_*ice 18 gcc properties objective-c llvm ios

编辑:我刚刚注意到这个其他Stack Overflow问题提出了同样的问题:为什么子类@property没有相应的ivar隐藏超类ivars?

这是一些有趣的行为,我无法在官方或非官方(博客,推文,SO问题等)中找到任何记录.我把它归结为它的本质,并在一个新的Xcode项目中进行了测试,但我无法解释它.

MyBaseClass有一个实例变量:

@interface MyBaseClass : NSObject {
    NSObject *fooInstanceVar;
}
@end
Run Code Online (Sandbox Code Playgroud)

MySubclass扩展了MyBaseClass,并声明了一个完全不相关的属性(也就是说,该属性不是由实例变量支持):

#import "MyBaseClass.h"
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end
Run Code Online (Sandbox Code Playgroud)

如果MySubclass的实现没有合成属性但实现了访问器方法,一切都很好(没有编译器错误):

#import "MySubclass.h"
@implementation MySubclass

- (NSObject*)barProperty {
    return [[NSObject alloc] init]; // pls ignore flagrant violation of memory rules.
}

- (void)setBarProperty:(NSObject *)obj { /* no-op */ }

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end
Run Code Online (Sandbox Code Playgroud)

但是,如果我删除属性访问器方法并将其替换synthesize为属性的声明,我会收到编译器错误:'fooInstanceVar' undeclared (first use in this function).

#import "MySubclass.h"
@implementation MySubclass
@synthesize barProperty;

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end
Run Code Online (Sandbox Code Playgroud)

如果我删除synthesize声明,或者如果我没有fooInstanceVar从MySubclass.m中引用实例变量,或者我将所有接口和实现定义放在单个文件中,则此错误消失.在GCC 4.2和GCC/LLVM构建设置中似乎也会发生此错误.

谁能解释一下这里发生了什么?

ıɾu*_*uǝʞ 5

正如在这个问题中回答:目标c xcode 4.0.2:子类无法访问超类变量"未在此范围内声明"

来自doc:Apple Objective-C Programming Langage:http: //developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163- CH12-TPXREF125

实例变量可以在声明它的类中以及在继承它的类中访问.没有显式范围指令的所有实例变量都具有@protected范围.

但是,可以在任何地方访问公共实例变量,就好像它是C结构中的字段一样.例如:

Worker*ceo = [[Worker alloc] init];

ceo-> boss = nil;

我使用LLVM GCC 4.2(对于iOS项目,在设备上)有编译错误:

错误:'fooInstanceVar'未声明(在此函数中首次使用)和使用GCC 4.2的同一个:错误:'fooInstanceVar'未声明(首次在此函数中使用)

我可以使用LLVM Compiler 2.0编译而不会出错.

使用self->编译LLVM GCC 4.2和GCC 4.2:

[NSArray arrayWithObjects:self.barProperty,self-> fooInstanceVar,nil]; 在doSomethingWithProperty方法中.


bbu*_*bum 0

编译器运行正常;禁止使用超类中的存储在子类中进行合成。

在某个时候,针对 llvm 提出了一个关于此的错误。它可能位于可公开访问的错误数据库中。

无论如何,请提交错误,要求澄清此特定规则。


我刚刚尝试过这个,它编译时没有警告。我不做什么?

@interface MyBaseClass : NSObject {
    NSObject *fooInstanceVar;
}
@end

@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end

@implementation MyBaseClass
@end

@implementation MySubclass
@synthesize barProperty;

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚您要解决什么问题。除了 32 位 Mac OS X 之外,所有实例变量在任何地方都是非脆弱的。