amit
amit

Reputation: 2331

access private (Class extensions) members in subclass

I'm using a 3rd party class that contain the following extention:

@interface BaseClass ()
{
   int privateMember;
}
@end

i've created my own subclass:

  @interface SubClass : BaseClass {
  }
  @end

is there a way to access privateMember in SubClass?


EDIT: actual code

GPUImageMovie.m: (base class)

@interface GPUImageMovie ()
{
    BOOL audioEncodingIsFinished, videoEncodingIsFinished;
    GPUImageMovieWriter *synchronizedMovieWriter;
    CVOpenGLESTextureCacheRef coreVideoTextureCache;
    AVAssetReader *reader;
}

MultiTrackGPUImageMovie.h (subclass)

@interface MultiTrackGPUImageMovie : GPUImageMovie {
}
...
@end

MultiTrackGPUImageMovie.m (subclass)

 - (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer forTarget:(int)targetToSendIdx {
 ...
 CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,       coreVideoTextureCache, movieFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight,   GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);
 ...
}

give error Use of undeclared identifier 'coreVideoTextureCache'

Upvotes: 3

Views: 2131

Answers (2)

Binarian
Binarian

Reputation: 12446

For me it is impossible to use the default @protected ivar from the class extension in the subclass like said the the accepted answer, when the class extension is in the .m file.

So here is how I could solve this issue without using the runtime API (which should not be used in such a manner).


They are implemented, also for the subclass `SubClass. You can not access them, because the declaration ist not visible to the subclass.

The subclass does not have access to the class extension @interface BaseClass () of the BaseClass.

You have 2 options:

Copy

@interface BaseClass () {
    int privateMember;
}
@end

to every subclass. Yes it is the class extension of the BaseClass inside the .m file of the SubClass.

OR

Create a .h file without a .m, only with the class extension code (like above) inside. Import that to the BaseClass and the SubClass.

Upvotes: 0

user529758
user529758

Reputation:

It depends on how the 'private' member has been declared. If there wasn't the @private keyword before it, i. e. it was really

@interface BaseClass ()
{
    int privateMember;
}
@end

and not

@interface BaseClass ()
{
    @private
    int privateMember;
}
@end

then you can easily reference this instance variable simply by using its name - the default access scope for instance variables is protected, i. e. not accessible outside the class, but accessible from subclasses.

However, if it was declared as private, you'll have to fall back using the runtime functions; in your subclass, declare and implement this method:

- (void *)pointerForIvarWithName:(NSString *)name
{
    Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
    return ((char *)self) + ivar_getOffset(ivar);
}

Then use it like this:

int ivarPtr;
ivarPtr = *(int *)[self pointerForIvarWithName:@"privateMember"];

Edit: so it seems the member you're trying to access is in a class extension and not public in the header file. In this case, you can go for the 2nd solution only (although it's not advised to do so).

Upvotes: 5

Related Questions