有什么方法可以在Objective-C中添加不在头文件(不使用LLVM 2.0或更高版本)中的iVar?

问题描述:

我最近得知你可以在LLVM2.0的类扩展中添加ivar。 (海湾合作委员会不能这样做) 这是不知何故真正私人iVar,因为其他用户不存在,因为它不在头文件。 喜欢:有什么方法可以在Objective-C中添加不在头文件(不使用LLVM 2.0或更高版本)中的iVar?

//SomeClass.h 
@interface SomeClass : NSObject { 

} 
@end 

//SomeClass.m 
@interface SomeClass() 
{ 
    NSString *reallyPrivateString; 
} 
@end 

@implementation SomeClass 

@end 

但这依赖于编译器。是否有任何其他方式来声明不在头文件中的伊娃?

声明实例变量的唯一地方是在接口或类扩展中(这实际上是接口的扩展)。但是,您可以随时使用associated object functions使用现代运行时有效地添加实例变量。

如果你正在实现一个库,并且想要隐藏你的实例变量,请看看苹果在UIWebView的界面中做了什么。他们有一个不公开头文件的内部webview。

@class UIWebViewInternal; 
@protocol UIWebViewDelegate; 

UIKIT_CLASS_AVAILABLE(2_0) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate> { 
@private 
    UIWebViewInternal *_internal; 
} 

如果你只是要在内部使用的伊娃,你正在使用的现代运行时(雪豹64位和iOS 3.0+,我认为),那么你可以在一个类中声明属性扩展并在课堂内综合它们。没有ivars暴露在你的头部,没有杂乱的物体,并且你也可以在易碎的ivars身边。

// public header 
@interface MyClass : NSObject { 
// no ivars 
} 
- (void)someMethod; 
@end 

// MyClass.m 
@interface MyClass() 
@property (nonatomic, retain) NSString *privateString; 
@end 

@implementation MyClass 
@synthesize privateString; 

- (void)someMethod { 
    self.privateString = @"Hello"; 
    NSLog(@"self.privateString = %@", self.privateString); 
    NSLog(@"privateString (direct variable access) = %@", privateString); // The compiler has synthesized not only the property methods, but also actually created this ivar for you. If you wanted to change the name of the ivar, do @synthesize privateString = m_privateString; or whatever your naming convention is 
} 
@end 

这适用于除了LLVM之外的Apple gcc。 (我不确定这是否适用于其他平台,即不是苹果的gcc,但它肯定适用于iOS和Snow Leopard +)。