Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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); }



You 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.


Fair 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));


What 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}>"
    }




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: