自动属性合成(@property)和继承

Anc*_*inu 42 warnings properties objective-c ios xcode5.1

使用XCode 5.1,会出现一个新警告.它让我明白 - 显然 -我做错了什么.

我们的想法是拥有一个对象(一个模型),它是从原始类继承的可变版本.这样的想法是要打开的是一个性质readonly,以readwrite

@interface Car : NSObject
    @property (strong, readonly) NSString *name;
@end

@interface MutableCar : Car
    @property (strong, readwrite) NSString *name;
@end
Run Code Online (Sandbox Code Playgroud)

这些需要在单独的文件中(如两个普通类).

它给出了这个警告:

Auto property synthesis will not synthesize property 'name' because it is 'readwrite' but it will be synthesized 'readonly' via another property
Run Code Online (Sandbox Code Playgroud)

所以我想知道什么是正确的解决方案来做类似的事情,如果它甚至可能的话.如果需要编写访问器并避免使用自动合成等.请准确,并用文档或其他任何方式支持您的答案.

fz.*_*fz. 59

我建议在MutableCar实现上明确合成该属性.如:

@implementation MutableCar

@synthesize name;

@end
Run Code Online (Sandbox Code Playgroud)

这样clang不会尝试使用自动合成

编辑:

如果您不想使用封装,并且出于其他原因需要从父类访问ivar,那么您需要做更多的努力:

首先,Car .h文件保持不变(我添加了printVar方法来打印ivar和属性):

@interface Car : NSObject

- (void)printVar;

@property (strong, readonly) NSString *name;

@end
Run Code Online (Sandbox Code Playgroud)

现在在.m文件中,我正在实现printVar方法,并且还添加了一个类扩展来告诉clang创建setter:

// Private class extension, causes setName: to be created but not exposed.
@interface Car ()

@property (strong, readwrite) NSString *name;

@end

@implementation Car

- (void)printVar
{
    NSLog(@"<Car> Hello %@, ivar: %@", self.name, _name);
}

@end
Run Code Online (Sandbox Code Playgroud)

现在您可以像以前一样创建MutableCar.h:

@interface MutableCar : Car

@property (strong, readwrite) NSString *name;

@end
Run Code Online (Sandbox Code Playgroud)

你的MutableCar.m应该是这样的:

@implementation MutableCar

@dynamic name;

- (void)printVar
{
    [super printVar];
    NSLog(@"<MutableCar> Hello %@", self.name);
}

@end
Run Code Online (Sandbox Code Playgroud)

这样,父级的_name ivar实际上是使用父级setter编写的,您可以访问它.

  • 解决方案是使用`@ dynamic`它解决了一切:) (8认同)