如何在objective-c中模拟受保护的属性和方法

Sha*_*yrs 7 protected objective-c xcode4.5

可能重复:
objective-c中的受保护方法

声明私有属性的方法很简单.

您声明在.m文件中声明的扩展名中.

假设我想声明受保护的属性并从类和子类访问它.

这是我试过的:

//
//  BGGoogleMap+protected.h
//
//

#import "BGGoogleMap.h"

@interface BGGoogleMap ()
@property (strong,nonatomic) NSString * protectedHello;
@end
Run Code Online (Sandbox Code Playgroud)

那是编译.然后我补充说:

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap ()

-(NSString *) protectedHello
{
    return _
}

@end
Run Code Online (Sandbox Code Playgroud)

问题开始了.我似乎无法在原始的.m文件之外实现类扩展.Xcode将要求该括号内的东西.

如果我做

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap (protected)

-(NSString *) protectedHello
{
    return _
}

@end
Run Code Online (Sandbox Code Playgroud)

我无法访问BGGoogleMap + protected.h中声明的_protectedHello的ivar

当然我可以使用常规类别而不是扩展名,但这意味着我不能拥有受保护的属性.

所以我该怎么做?

rob*_*off 7

Objective-C编程语言说:

类扩展类似于匿名类,除了它们声明的方法必须@implementation在相应类的主块中实现.

所以你可以在类的main中实现类扩展的方法@implementation.这是最简单的解决方案.

更复杂的解决方案是在类别中声明"受保护"消息和属性,并在类扩展中声明该类别的任何实例变量.这是类别:

BGGoogleMap+protected.h

#import "BGGoogleMap.h"

@interface BGGoogleMap (protected)

@property (nonatomic) NSString * protectedHello;

@end
Run Code Online (Sandbox Code Playgroud)

由于类别无法添加要保留的实例变量protectedHello,因此我们还需要一个类扩展:

`BGGoogleMap_protectedInstanceVariables.h"

#import "BGGoogleMap.h"

@interface BGGoogleMap () {
    NSString *_protectedHello;
}
@end
Run Code Online (Sandbox Code Playgroud)

我们需要在主@implementation文件中包含类扩展,以便编译器在.o文件中发出实例变量:

BGGoogleMap.m

#import "BGGoogleMap.h"
#import "BGGoogleMap_protectedInstanceVariables.h"

@implementation BGGoogleMap

...
Run Code Online (Sandbox Code Playgroud)

我们需要在类@implementation文件中包含类扩展,以便类别方法可以访问实例变量.由于我们protectedHello在一个类别中声明了属性,因此编译器不会合成setter和getter方法.我们必须手工编写:

BGGoogleMap+protected.m

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap (protected)

- (void)setProtectedHello:(NSString *)newValue {
    _protectedHello = newValue; // assuming ARC
}

- (NSString *)protectedHello {
    return _protectedHello;
}

@end
Run Code Online (Sandbox Code Playgroud)

应该导入子类BGGoogleMap+protected.h以便能够使用该protectedHello属性.它们不应导入,BGGoogleMap_protectedInstanceVariables.h因为实例变量应该被视为对基类的私有.如果您运送的是没有源代码的静态库,并且您希望库的用户能够进行子类化BGGoogleMap,请运送BGGoogleMap.hBGGoogleMap+protected.h标头,但不要发送BGGoogleMap_protectedInstanceVariables.h标头.