2

我最近了解到您可以使用 LLVM2.0 在类扩展中添加 ivar。(gcc 不能这样做)这在某种程度上是真正私有的 iVar,因为其他用户不存在它,因为它不在头文件中。像:

//SomeClass.h
@interface SomeClass : NSObject {

}
@end

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

@implementation SomeClass

@end

但这确实依赖于编译器。有没有其他方法可以声明不在头文件中的 ivar?

4

3 回答 3

1

声明实例变量的唯一地方是在接口或类扩展(实际上是接口的扩展)中。但是您可以随时使用关联的对象函数在现代运行时有效地添加实例变量。

于 2011-04-12T19:30:13.003 回答
0

如果您正在实现一个库并想要隐藏您的实例变量,请查看 Apple 在 UIWebView 界面中所做的工作。他们有一个不公开头文件的内部 web 视图。

@class UIWebViewInternal;
@protocol UIWebViewDelegate;

UIKIT_CLASS_AVAILABLE(2_0) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate> { 
 @private
    UIWebViewInternal *_internal;
}
于 2011-04-12T17:39:39.613 回答
0

如果您只是在内部使用 ivar,并且您使用的是现代运行时(我认为是 Snow Leopard 64 位和 iOS 3.0+),那么您可以在类扩展中声明属性并在类中合成它们. 没有 ivars 暴露在你的标题中,没有凌乱的id _internal对象,你也可以绕过脆弱的 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。(我不确定这是否适用于其他平台,即不是 Apple 的 gcc,但它肯定适用于 iOS 和 Snow Leopard+)。

于 2011-04-12T19:12:58.950 回答