Skip to content

Instantly share code, notes, and snippets.

@pookjw
Created March 9, 2025 09:13
Show Gist options
  • Save pookjw/4f9a2ce7ddfa45c77ebe130a2cfd9cce to your computer and use it in GitHub Desktop.
Save pookjw/4f9a2ce7ddfa45c77ebe130a2cfd9cce to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <objc/message.h>
#import <objc/runtime.h>
OBJC_EXPORT id objc_msgSendSuper2(void); /* objc_super superInfo = { self, [self class] }; */
@interface MyObject : NSObject {
NSUInteger _integer;
}
@property (assign, nonatomic, setter=custom_setInteger:) NSUInteger integer;
@end
@implementation MyObject
+ (id)_createValueSetterWithContainerClassID:(id)classID key:(NSString *)key {
if ([key isEqualToString:@"integer"]) {
Method method = class_getInstanceMethod(self, @selector(custom_setInteger:));
id setter = ((id (*)(id, SEL, id ,id, Method))objc_msgSend)([objc_lookUpClass("NSKeyValueMethodSetter") alloc], sel_registerName("initWithContainerClassID:key:method:"), classID, key, method);
return setter;
}
struct objc_super superInfo = { self, [self class] };
return ((id (*)(struct objc_super *, SEL, id, id))objc_msgSendSuper2)(&superInfo, _cmd, classID, key);
}
- (NSUInteger)integer {
return _integer;
}
- (void)custom_setInteger:(NSUInteger)integer {
_integer = integer;
}
@end
@interface Observer : NSObject
@end
@implementation Observer
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"%@ %@ %@", keyPath, object, change);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyObject *object = [MyObject new];
Observer *observer = [Observer new];
[object addObserver:observer forKeyPath:@"integer" options:NSKeyValueObservingOptionNew context:NULL];
object.integer = 3;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment