开发者

Is there any way to access the address of private instance variable of any class in objective c runtime?

Is there way to access address of private instance variable of any class by using objective c runtime?

开发者_StackOverflow中文版

for example:

 self.navigationItem.title 

Is there any way to get address of _title ivar of UINavigationItem class?

Thanks


Obvious observations: self.navigationItem.title may not be an instance variable, as a getter can do anything it likes to generate a result and the dot notation just calls the getter. Even if it is an instance variable in this version of the OS it may not have been in the past and may not be in the future. Even if title is directly backed by an instance variable, it may not be named _title — it could be called anything whatsoever.

Even in the case where you do know for certain that a class has a particular instance variable, the relevant mechanisms are removed as of Objective-C 2.0. Under the older runtime you could have used:

#import <objc/runtime.h>

...
Ivar instanceVariable = class_getInstanceVariable([instance class], "varName");
// yes, really, a C-style string

NSLog(@"offset of that var is %d", instanceVariable->ivar_offset);

Or, similarly:

struct exampleClassStruct
{
    @defs(exampleClass);
};
// this is now a struct with the same layout all the same instance variables
// as exampleClass

However, you'll now be met with errors like "Invalid application of @defs in non-fragile ABI". So, in conclusion: you can't do what you want to do. Probably the closest thing is to use class_GetProperty, which — like dot notation — doesn't care about memory layouts or whether the thing has the same name or even is really an instance variable. Failing that, class_getInstanceMethod (on the same page) can be used to get a C function pointer to the getter.

EDIT: a quick extra observation, after following alastair's comment below, is that the runtime provides id object_getIvar(id object, Ivar ivar) (link) and a set equivalent, which are the opaque ways to get and set instance variables on a particular class given that their address is now obscured. Those take the Ivar that you get from either class_getInstanceVariable or object_getInstanceVariable so probably aren't doing any sort of complicated lookup, and explain why you can still get Ivars even though the associated struct now has no public members whatsoever.

EDIT2: please see discussion with alastair below; the final parameter of object_getInstanceVariable and/or the result of ivar_getOffset may be usable to do what you want, depending on your interpretation of the documentation. Supposing you adopt the same reading as alastair, then either of the following would do what you want (coded extemporaneously):

#import <objc/runtime.h>

void *pointerToInstanceVariableA(id object, const char *variableName)
{
    Ivar instanceVar = class_getInstanceVariable([object class], variableName);
    return (unsigned char *)object + ivar_getOffset(instanceVar);
}

void *pointerToInstanceVariableB(id object, char *variableName)
{
    void *returnValue;
    Ivar instanceVar = object_getInstanceVariable(object, variableName, &returnValue);
    return returnValue;
}


I have a view controller and I needed the property from the base class. It's name was defined as so

@property ( nonatomic, strong ) NSString *ModuleName;

the code to access it without any knowledge of the class

The code to get an instance of a custom view controller

    id viewCtrl = [appDelegate returnTestView];

now I grab the value ( no knowledge of any class )

    Ivar instanceVariable = class_getInstanceVariable([viewCtrl class], "ModuleName");
    NSString *privateValue = (NSString *) object_getIvar(viewCtrl, instanceVariable);
    NSLog(@"Your value is %@", privateValue);

The actual method in my appDelegate is

- (id)returnTestView {
    return [[TestViewController alloc] init];
}

The init of my custom view controller

@interface TestViewController : UIViewController

- (id)init {
    self = [super init];
    if (self) {
        // Custom initialization
        self.ModuleName = @"Hello World";
    }
    return self;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜