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;
}
精彩评论