简体   繁体   中英

Is there any way to add an iVar that's not in the header file (not using LLVM 2.0 or later) in Objective-C?

I recently learned that you can add ivar in a class extension with LLVM2.0. (gcc can't do this) This is somehow really private iVar because other users don't it's existence since it's not in the header file. like:

//SomeClass.h
@interface SomeClass : NSObject {

}
@end

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

@implementation SomeClass

@end

But this does rely on the compiler. Is there any other way to declare an ivar that's not in the header file?

The only place to declare instance variables is in the interface or a class extension (which is really an extension of the interface). But you can effectively add instance variables at any time with the modern runtime using the associated object functions .

If you are implementing a library and want to hide your instance variables take a look at what Apple does in the interface for UIWebView. They have an internal webview that does not expose a header file.

@class UIWebViewInternal;
@protocol UIWebViewDelegate;

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

If you're just going to be using the ivar internally, and you're using the modern runtime (Snow Leopard 64 bit and iOS 3.0+, I think) then you can just declare properties in a class extension and synthesize them inside the class. No ivars are exposed in your header, no messy id _internal objects, and you get around fragile ivars, too.

// 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

This works with Apple's gcc, in addition to LLVM. (I'm not sure if this works on other platforms, ie not Apple's gcc, but it will certainly work for both iOS and Snow Leopard+).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM