How to create a dynamic getter / setter agent?

I want to add a method to implement a property at runtime. Add I use + resolveInstanceMethod, class_addMethod. But below the code, in dynamicN () and dynamicSetN (), they cannot be compiled, and I donโ€™t know how to use C-Function to set / get an instance variable without synthesize property.

#import <Foundation/Foundation.h> #import <objc/runtime.h> float dynamicN(id self, SEL _cmd) { NSString *methodName = NSStringFromSelector(_cmd); NSLog(@"%@,%@", methodName, [self description]); // return [self n]; } void dynamicSetN(id self, SEL _cmd, float sname) { printf("setName start;\n"); // self.n = sname; } @interface bird : NSObject { int height; float n; } @property float n; @property int height; @end @implementation bird @synthesize height = height; @dynamic n; - (id)init { if (self = [super init]) { n = 1.0; height = 3; } return self; } - (float) n { return n; } + (BOOL) resolveInstanceMethod:(SEL)aSEL { if (aSEL == @selector(n)) { //class_addMethod([self class], aSEL, (IMP) dynamicN, " f@ :"); //return YES; } if (aSEL == @selector(setN:)) { class_addMethod([self class], aSEL, (IMP) dynamicSetN, " v@ :f"); return YES; } return [super resolveInstanceMethod:aSEL]; } @end int main(int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; bird *aBird = [[bird alloc] init]; aBird.n = 3; printf("\n%f\n,%d", aBird.n, aBird.height); [pool drain]; return 0; } 
+4
source share
2 answers

@ H2CO3 is right for your setter. A dynamic getter has the same underlying problem. You are trying to call [self n] , which is not in id . That is why it will not compile. (As @ H2CO3 notes, this will result in a warning, not an error, you all use -Werror , right?) But more importantly, even if it would It would be an infinite loop. self.n is just a call to [self n] , which will return to this function.

If you're looking for examples, you can download the code for chapter 20 of iOS 6 Programming Pushing the Limits . See the Person project for Person.m . Chapter 28 contains much more explanations on how to implement this feature if you are interested.

Please note that the correct name in ObjC is very important. Your class should be Bird , not Bird . Obtaining a naming convention under your belt is crucial before attempting to use additional features such as dynamic dispatch.

+2
source

Your setter will not compile because your self parameter is of type "id", which in itself does not have a property named "n". You will want to drop it, and then directly look for it:

 ((bird *)self)->n = sname; 

Your recipient seems good, though, I donโ€™t know why it cannot be compiled.

+2
source

Source: https://habr.com/ru/post/1390275/


All Articles