3 ms·
In Objective-C we can create methods, properties and classes on the fly using <objc/runtime.h> Here's how to create a property on the fly (great for categories
by sandoze 13y ago
In Objective-C we can create methods, properties and classes on the fly using <objc/runtime.h>
Here's how to create a property on the fly (great for categories)
@dynamic progressView;
- (void)setProgressView:(ACProgressView )progressView {
objc_setAssociatedObject(self, ACProgressViewKey, progressView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (ACProgressView )progressView {
return objc_getAssociatedObject(self, ACProgressViewKey);
}
- wrs 13y agoYou still had to tell the compiler ahead of time about the property. The actual test is more like NSObject obj = [NSObject init]; giveObjectAProperty(obj, @"progressView"); obj.progressView = [NSNumber 42]; Writing giveObjectAProperty may not be "nearly impossible" but it sure isn't easy. And of course the parent is talking about methods, not properties, but...same argument.
- sandoze 13y agoFair enough. Here's how you'd make that class on the fly: Class mySubclass = objc_allocateClassPair([NSObject class], "MySubclass", 0); Here's how you'd add a description method to a newly created class: static NSString *Description(id self, SEL _cmd){ return [NSString stringWithFormat: @"<%@ %p: foo=%@>",[self class], self, [self foo]]; } // add Description to mySubclass // grab NSObject's description signature so we can borrow it Method description = class_getInstanceMethod([NSObject class], @selector(description)); const char *types = method_getTypeEncoding(description); // now add class_addMethod(mySubclass, @selector(description), (IMP)Description, types); And your iVars: class_addIvar(mySubclass, "foo", sizeof(id), rint(log2(sizeof(id))), @encode(id));
- 10char 13y agoWhat jballanc is saying is that yes these things are possible in Objective-C, but the technique of doing these tricks in Ruby/Motion is an order of magnitude simpler and idiomatic: klass = Object.const_set "MySubclass", Class.new(Object) klass.send(:attr_accessor, :foo) klass.send(:define_method, "description") { "<#{self.class}: foo=#{self.foo}>" }