Objective-C Runtime - Ivar

This post shows how to read and write an instance var in another class.

Suppose we have a class 'ReadOnly'

@interface ReadOnly : NSObject{
        @private int value;
}
@property (readonlyint data;
@end

So, if we want to set data or value in other class, we can take advantage of objc runtime feature.

        ReadOnly * obj = [[ReadOnly alloc] init];

        Ivar ivar1 = class_getInstanceVariable(object_getClass(obj), "value");
       int *ivarPtr1 = (int *)((uint8_t *)obj + ivar_getOffset(ivar1));
*ivarPtr1 = -1;
        // obj.value = -1;

        Ivar ivar2 = class_getInstanceVariable(object_getClass(obj), "_data");
    int *ivarPtr2 = (int *)((uint8_t *)obj + ivar_getOffset(ivar2));
*ivarPtr2 = 1;
        // obj.data = 1;

6 thoughts on “Objective-C Runtime - Ivar”

  1. 实际上并没有修改啊,给obj加个方法,输出data的值,发现并没有改变「」;其次这句话编译不过:
    int *ivarPtr1 = (int *)((uint8_t *)obj + ivar_getOffset(ivar1));

    1. 首先需要
      #import <objc/runtime.h>
      其次,在Build Settings里要设置
      Objective-C Automatic Reference Counting为No

      1. 输出:
        2016-06-28 13:16:07.997394 ivar[92542:3806138] value -1
        2016-06-28 13:16:07.997597 ivar[92542:3806138] data 1
        2016-06-28 13:16:07.997617 ivar[92542:3806138] 1
        Program ended with exit code: 0

        代码:

        #import <Foundation/Foundation.h>
        #import <objc/runtime.h>
        
        @interface ReadOnly : NSObject {
            @private int value;
        }
        @property (readonly) int data;
        @end
        
        @implementation ReadOnly
        
        - (void)print {
            NSLog(@"value %d", value);
            NSLog(@"data %d", [self getData]);
        }
        
        - (int)getData {
            return _data;
        }
        
        @end
        
        int main(int argc, const char * argv[]) {
            @autoreleasepool {
                ReadOnly * obj = [[ReadOnly alloc] init];
                
                Ivar ivar1 = class_getInstanceVariable(object_getClass(obj), "value");
                int *ivarPtr1 = (int *)((uint8_t *)obj + ivar_getOffset(ivar1));
                *ivarPtr1 = -1;
                // obj.value = -1;
                
                Ivar ivar2 = class_getInstanceVariable(object_getClass(obj), "_data");
                int *ivarPtr2 = (int *)((uint8_t *)obj + ivar_getOffset(ivar2));
                *ivarPtr2 = 1;
                // obj.data = 1;
                
                [obj print];
                NSLog(@"%d", obj.data);
            }
            return 0;
        }
        

Leave a Reply

Your email address will not be published. Required fields are marked *

twenty + 13 =