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

RubyMotion is not a wrapper. It is an implementation of Ruby on the Obj-C runtime. This means that a RubyMotion object is an Obj-C object (for comparison, a Ruby object in MRI is just a C struct). So why would you want to use RubyMotion? Well...

* Obj-C, from the very start, was implemented as a strict superset of C. This means that every valid bit of C code must also be valid Obj-C. This places some rather sever limitations on the Obj-C syntax. Ruby does not have this limitation, and neither does RubyMotion. So one reason you might use RubyMotion is to get a cleaner syntax that does the same thing as Obj-C.

* The Obj-C runtime is very dynamic. You can create classes on the fly, add methods to them at runtime, move methods around between objects, and create methods dynamically. The Obj-C language makes it nearly impossible to take advantage of any of these features of the Obj-C runtime. So another reason you might use RubyMotion is to get the most out of the Obj-C runtime.



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


That was really informative. Thanks for the breakdown.


There are a few very well-written wrappers that make utilizing the Obj-C runtime much easier. MAObjCRuntime [1] is a good example of such a wrapper. Look at MACollectionUtilities [2] as an example of how to use MAObjCRuntime.

[1]: https://github.com/mikeash/MAObjCRuntime [2]: https://github.com/mikeash/MACollectionUtilities


Bullet #2 is so very very wrong. Nice try. I can't speak to the first bullet.


Please elaborate; I have only minimal experience with ObjC and do not use Ruby in the context of native development, so any well-described counterpoints would be much appreciated.

Edit: I obv. didn't write your parent comment. What I meant was that I'm sure others in my position, having read your parent, would appreciate more elaboration from you as well. :)


Sorry, you're right. It was an off the cuff rebuttal with no substance. Added to the parent comment.


I think he meant ruby in bullet 2




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

Search: