Build iOS Apps In Ruby - Available Summer '12
mobiruby.org
mobiruby.org
alert = UIAlertView._alloc \
._initWithTitle _S("Hello"),
:message, _S("I'm MobiRuby"),
:delegate, nil,
:cancelButtonTitle, _S("I know!"),
:otherButtonTitles, nil
alert._show
supposed to be better than this ? alert = [[UIAlertView alloc]
initWithTitle:@"Hello"
message:@"I'm ObjC"
delegate:nil
cancelButtonTitle:@"I know!"
otherButtonTitles:nil];
[alert show];file.rb:
require 'stuff'
class foo
def something
alert = UIAlertView._alloc \
._initWithTitle _S("Hello"),
:message, _S("I'm MobiRuby"),
:delegate, nil,
:cancelButtonTitle, _S("I know!"),
:otherButtonTitles, nil
alert._show
end
end
Instead offile.h
#import <stuff>
@interface foo
-(void)something:(BOOL)what andthen:(CGRect)thisthing
@end
and then file.m #import <otherstuff>
#import <yetmorestuff>
#import "file.h"
#import <oh shit is this in the right place?.h>
#import <i think this is ok>
#define SOME_HACK
#import <this better come after that define up there.h>
@implementation foo
-(void)something:(BOOL)what butthen:(CGRect)thisthing
{
alert = [[UIAlertView alloc]
initWithTitle:@"Hello"
message:@"I'm ObjC"
delegate:nil
cancelButtonTitle:@"I know!"
otherButtonTitles:nil];
[alert show];
}
Fuck that.1. Don't Repeat Yourself. Computer have more memory than 1986.
2. Don't forget to turn on warnings-as-errors, otherwise that code above will compile and then break because (of course you noticed) the method declaration doesn't actually match the declaration but the compiler doesn't care because its a brutal hack.
Even outside of that, though, there are a LOT of things that you can do with MacRuby a lot cleaner thanks to it being Ruby over its Objective-C counterpart. Try launching an external process, for example. It's 5-8 lines of code at the very least in Objective-C (and it's not as flexible), whereas it's 1-3 easy to read lines in Ruby, depending on how much control and feedback you want.
I think as it matures, we'll see some wrappers that will make MobiRuby closer to what people are wanting to see from a Ruby-on-iOS solution; it's weird that you guys seem to have no vision for this sort of thing.
My cofounder did a nice talk on our experiences: http://www.madebysofa.com/archive/blog/pyobjc-and-cocoa/inde...
In the world of OS X/iOS the frameworks are really important. You have to understand them. You have to work with them. It is not uncommon that you need much more time to get familiar with a framework than to get familiar with Objective-C.
Take Core Data for example: Core Data is an extremely cool framework but you need a couple of days to understand the basics, a couple of weeks to understand the advanced concepts and years to really master it.
Objective-C is a pretty easy programming language.
So a a conclusion: Does it really make sense to replace Objective-C with - lets say Ruby? What do you gain? Lets assume you already know Ruby - then it saves you to learn Objective-C. But 90% of the time you will deal with the frameworks - not with the language. In my opinion it does not really make sense to use Ruby instead of Objective-C because you save so little.
Obj-C really falls down for more complex algorithms, data structures, and text handling. You can do this kind of thing in Obj-C, of course, but the verbosity really gets in the way. A higher-level language like Ruby would be great for this but maybe the new object literals coming in Obj-C will help close the gap.
The problem with writing glue code in a scripting language is that it doesn't really buy you much unless you can impose a new, higher-level abstraction on the existing UI. As these examples show, you haven't really improved on Cocoa if all you've done is changed the function calling syntax.
While this project isn't going to do much to simplify my Cocoa code, the rest of my app could be much simpler as a result.
Expressiveness is subjective too, but in this context talks about ability to express concepts in elegant or clear ways.
This is nonsense.
Objective C is a fantastic language. Appcelerator Titanium, PhoneGap - it's all crap. Customers can feel the difference.
To make a native app, learn a native language.
"Oh I've been looking into PhoneGap, it's pretty cool"
"Oh I've been learning Android development"
WHY???? When has a client even asked us to make an Android app.
Doesnt seem to save any time at all.
MacRuby does a bit better job at first glance than this does, but you can't get past the way the framework you're using works.
In Objective-C:
Person *person = [Person new];
[person name];
[person setName:name];
[person setFirstName:first lastName:last];
and in MacRuby person = Person.new
person.name
person.setName(name)
person.setFirstName(first, lastName:last)
As far as I can tell in MobiRuby that'd look something like this: person = Person._alloc._init
person._name
person._setName _S(name)
person._setFirstName _S(first), :lastName, _S(last) person = Person.new
person.update_attributes(:name => 'Joe', :surname => 'Blogs')
OR
person = Person.new
person.name = "Joe"
person.last_name = "Blogs"
So why not just use ObjC and call a bundled script which deals well with a specific problem in a rubyish way, and takes input from files, rather than mixing up the two paradigms and ending up with a Frankenstein language which is harder to parse from both sides? I think Apple bans calling bundled scripts on iOS (or did, not sure if the rules have changed), but that's not a technical problem but a political one.I understand people might want to try to use the strengths of Ruby (munging text, some nice libraries), but to get there, you're throwing out some of the nicest things about Ruby - a lovely syntax that doesn't get in your way, and method names you can easily guess. Usually writing Ruby I find I don't have to look up methods and can stay in the flow, but I can't say the same about the cocoa API, with NSString in particular full of huge method names and bizarre syntax for simple operations. So this is throwing out that advantage for the dubious advantage of being able to call cocoa methods from Ruby (using a weird syntax).
YMMV
person = Person.new
person.name = "Joe"
person.lastName = "Blogs" alert = UIAlertView._alloc \
._initWithTitle _S("Hello"),
:message, _S("I'm MobiRuby"),
:delegate, nil,
:cancelButtonTitle, _S("I know!"),
:otherButtonTitles, nil
alert._show
Presumably you don't want to stray from UIKit method names in order to make translation automatic, which is understandable, however translation could be automatic couldn't it - is all that _S necessary? Did you consider a chained, hash syntax something like this: alert = UIAlertView.alloc().initWithTitle(:title => 'Hello',
:message => "I'm MobiRuby",
:delegate => nil,
:cancelButtonTitle => "I know!",
:otherButtonTitles => nil).show()
With the syntax above someone could omit nil arguments and still get the right result, if you fill in missing arguments for them.Or would that not work for some reason? I understand why you need to keep the method names (for automatic translation), but perhaps the syntax could be a little friendlier and more in line with expectation for Ruby code? I would love to write code for iOS in Ruby (have already written some, but it wouldn't get on the app store due to restrictions), but interfacing with views etc is not too painful in ObjC currently, so if it was more painful in something like this it would put me off.
Having looked at your pages further, I see the possibilities of a cross-platform Ruby framework for iOS and Android or WinMo, but if you tie it so tightly to UIKit, how did you plan handling cross-platform issues elegantly? Would that be down to the developers (it is a huge task of course)?
Sure, there will always be some apps that will need to be coded close to the metal in C/C++ for maximum performance. But now we're seeing more and more that even on mobile devices we have enough power that we can afford to write most apps primarily or even entirely in "managed" languages like Lua, Java, and (apparently) Ruby.
At some level you need native code.
For me, I want something like Ruby that generates native code.
I'm not optimistic about trying to generate good native code from a language like Ruby. You need much more control over memory layout, just for starters, to get real native speeds.
From an engineering point of view i have to say that this is impressive, very keen to see what tools you come up with to aid the development process, a TextMate bundle to compile and deploy to the sim would be super sweet ;-)
(Just to establish that I'm not completely talking out my rear end: I've been programming Objective-C for ten years, Ruby for five.)
I agree with you that the verbosity of ObjC makes it harder to mentally parse fast, but I also think there is a lot of clarity to it when you read it slow.
Where I see ObjC fall down is more in terms of command verbosity. For example in Ruby,
File.open("readfile.rb", "r") do |infile|
while (line = infile.gets)
puts "#{line}"
end
end
...would be ~150 lines of code in ObjC (Dave DeLong: http://stackoverflow.com/a/3711079/196358). Which is not really a failing of the language, actually. It's a failing of the libraries that come with the language.Apple chose to give you a couple ways to read a file. The easy way is `stringWithContentsOfFile:encoding:error:error`, but the next level of control is way to low level. Dave DeLong's solution to reading a file line by line exposes an api that looks like this:
DDFileReader * reader = [[DDFileReader alloc] initWithFilePath:pathToMyFile];
[reader enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) {
NSLog(@"%@", line);
}];
Not actually much more complex or verbose than the ruby.The extremes are probably not the place to be.
Why do you think verbose languages are so loved by big enterprise companies?
It is a total different scale of development.