MacRuby & HotCocoa Tasty Apps for OS X Thilo Utke 2009
May 15, 2015
MacRuby & HotCocoaTasty Apps for OS X
Thilo Utke 2009
OverviewAbout - Web developer - macruby - - Upstream - Alex - Web developer - WebApplications - doningtext - forex-metal - In business for a while - bootstrap - Paper-C - fast - rails - ruby - reliable - testing - rspec - cucumber - ruby - reliable - macs - ruby - rails - text mate - fast - plugins - gems - tools - interesting techs - iphone - mac - tools - Objective-C - features like ruby - smalltalk - more code - Hello World Example - not so fast - unlike ruby - dropped it - heard about macruby 0.3 relase - on top of Obj-C - get curious - less code - on Mac - with Cocoa - major API - Desktop Applications - More like ruby - liked it - Its from Apple! - from - RubyWrapper for NSObject 2001 - Integration with ProjectBuilder (IB 2002) - 2006 Laurent Sansonetti - 10.5 shipped with OS X - 2008 MacRuby shall replace RubyCocoa - RubyCocoa is a scripting Bridge - Syntactic Sugar - Syntax Mismatch - 2 Object Graphs - Green Threads vs. native Threads - Ruby 1.8 and ObjectiveC - Standard Libs Broken - Slow!!! - Mismatch like String != NSString => more Code - Picture - Ruby first Class Citizen - MacRuby - Ruby 1.9 - Native Threads - Matches better with Obj Syntax - Faster - Tighter Integration with Obj-C - Share Base classes - Share Infrastructure - GC - MacRuby 0.5 - the best Ruby for Mac - In Development - NO GLI - Share IO - On top of LLVM - Doing optimizations - Calls Obj-C - class/methods/obj all Obj C - show Methods - No more libffi but uses a new C-dispatcher - Picture! - Show Mixing MacRuby with ObjC - Compiles Code JIT - soon AOT - other Platforms - iPhone? - IB integration! - Framework - main_rm - Outlet - Action - Delegates - Like ActiveRecord Callbacks - but fixed names - you tell who handle it - first responder - Delegate for Application - Show Random Number Gen with IB - Code Obj-C/MacRuby-
All the things I’d like to talk about.
OutlineIntro
Objective-C Encounter
Apple - Ruby
RubyCocoa
MacRuby 0.5
MacRuby <-> Obj-C
Interface Builder Integration
Back to Code with HotCocoa
Impact
I’m a WebDeveloper.
UPSTREAM
My Company
Alexander Lang, also Founder and Owner of Upstream
Wrote CouchPotato. Talks about Ruby Libs for CouchDB
We did Community, Productivity, Finance and Educational Websites. Our own product is doingText.com
Rails enabled us to build WebApps really fast.
Text
I love Ruby!
To be fast and deliver reliable applications, we build software with test first.
New libraries, gems and technics keep WebDevelopment interesting.
Boring!!!!
www.flickr.com/photos/ipom
Still I get bored easily, so I play with new technologies.
Thats why I have an iPhone.
That’s why Alex has an iPhone.
That’s why we play with couchDB.
That’s why I thought Obj-C might be interesting.
Obj-CRuby
SmallTalk
Ruby and Obj-C have a common ancestry.
Obj-CRuby
Reflective
Dynamic
Garbage Collection
Object Oriented
Characteristics they have in common.
Obj-CRuby
Closures
FFI, C-Ext C-SuperSet
methodname(1,2) method: 1 name:2
Interpreter Compiler
Things that differ.
Grabbed this book to start with Obj-C.
First Objective-C App@interface Foo : NSObject{ IBOutlet NSTextField *textField;}
- (IBAction)gerneate:(id)sender;- (IBAction)seed:(id)sender;@end
@impelemtation Foo
- (IBAction)generate:(id)sender{ int generated = (random() % 100) +1; [textField setIntValue:generated];}
- (IBAction)seed:(id)sender{ srandom(time(NULL)); [textField setStringValue:@"Generator seeded"];}
My first Obj-C code with header files, types, many braces and semicolons.
o_0Felt like back in C programming class. Thrown Obj-C away.Yes, Ruby spoiled me.
MacRuby 0.3
Heard about MacRuby with the 0.3 release.
First Objective-C Appclass Foo attr_writer :text_field def seed(sender) @text_field.StringValue = "Generator doesn't need to be seeded ;)" end def generate(sender) @text_field.StringValue = (rand(100) + 1) endend
Same Obj-C Tutorial App with MacRuby.
\0_0/Header files, types, braces, and semicolons are gone. Much less code. Yeah!
It is from Apple!
Apple wants Ruby to be a
first class citizen
on OS X
Where that comes from.
2001
Ruby extension for NSObject
and NSClassFromString function
by Hisakuni Fujimoto
2002
RubyCocoa Project
Ruby 1.6.7 on OS X 10.2
2005
Ruby 1.8.2 on OS X 10.4
For a long time nothing happened.
2006
Laurent Sansonetti from Apple joined RubyCocoa
Things started to move.
2007
Ruby 1.8.6, Rails, RubyGems
and RubyCocoa
on OSX 10.5
Big move
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
RubyCocoa Architecture
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
Use Objects from Obj-C in Ruby and vice versa
Syntax matching
[Class initWith:(type) p1 other:(type) p2]
Class.initWith_other(p1, p2)
Extending/Inheriting/Overwriting
Access to C-Structs
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
Messaging between Obj-C and Ruby is slow!
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
Two Object Spaces
"Hi" != @"Hi"
Green Threads vs. Native Threads
RubyCocoa can run only on the MainThread.Ruby needs patching to allow to work with the Obj-C runtime.
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
Duplicated infrastructure
RubyCocoa
Obj-C Runtime
GCC
Obj-C
IO
Frameworks
GC
MRI 1.8
Ruby Code GC
Std LibApp
Bridge
Duplicated libraries
Ruby’s causing hang ups
Thanks to RubyCocoa for some cool apps, like GitNub.
2008
MacRuby
shall replace RubyCocoa
in the future
The appearance of MacRuby
2009
MacRuby gets popular
Ruby 1.8.7, Rails 2.3, RubyGems
and RubyCocoa
on OSX 10.6
Community starts to grow.Gets buzz, because it for example faster than YARV.Appears more in screencasts/conferences.
Apple Stayes true to ruby
MacRuby 0.5
Obj-C Runtime
GCC
LLVMJIT/AOT
Ruby Code
GC
Obj-C
Std LibApp
IO
Frameworks
MacRuby architecture
MacRuby 0.5
Obj-C Runtime
GCC
LLVMJIT/AOT
Ruby Code
GC
Obj-C
Std LibApp
IO
Frameworks
Object => NSObject
RubySpecific extensions
Same Primitives
./miniruby -e 'p Array.new.methods(true, true)'
[:"sortUsingFunction:context:", :"exchangeObjectAtIndex:withObjectAtIndex:", :removeAllObjects, :"getObjects:range:", :"containsObject:inRange:", :removeObjectsInRange, :removeObjectAtIndex, :removeLastObject, :"replaceObjectAtIndex:withObject:", :"insertObject:atIndex:", :addObject, :"countByEnumeratingWithState:objects:count:", :objectAtIndex, :count, :mutableCopyWithZone, :copyWithZone, :classForCoder, :finalize, :hash, :isEqual, :sortUsingDescriptors, :filterUsingPredicate, :initWithContentsOfURL, :initWithContentsOfFile, :sortUsingSelector, :"removeObjectsFromIndices:numIndices:", :removeObjectsAtIndexes, :"replaceObjectsAtIndexes:withObjects:", :"insertObjects:atIndexes:", :"sortUsingFunction:context:range:", :"initWithObjects:count:", :initWithCapacity, :removeObjectsInArray, :"removeObjectIdenticalTo:inRange:", :removeObjectIdenticalTo, :"removeObject:inRange:", :removeObject, :"removeObject:range:identical:", :setArray, :"setObject:atIndex:", :addObjectsFromArray, :"replaceObjectsI
With the extra second argument set on true, you can see the Obj-C methods.
MacRuby 0.5
Obj-C Runtime
LLVM
LLVMJIT/AOT
Ruby Code
GC
GCC
Std LibApp
IO
Frameworks
Generate Obj-C calls for Ruby code
Intermediate Representation (IR)
Optimization
JIT compiler to execute code
~ 3 x faster than YARV
AOT compiler very soon
LLVM = Low Level Virtual Machine
MacRuby 0.5
Obj-C Runtime
LLVM
LLVMJIT/AOT
Ruby Code
GC
GCC
Std LibApp
IO
Frameworks
Generate Obj-C calls for Ruby code
Intermediate Representation (IR)
Optimization
JIT compiler to execute code
~ 3 x faster than YARV
AOT compiler very soon
AOT Compiler might allow to build for the iPhone. The garbage collection is still an open question.
VM_DUMP_IR=1 ./miniruby -e 'p "Hello RailsWayCon!"'
"Hello RailsWayCon!"IR dump ----------------------------------------------; ModuleID = 'Roxor'
define i64 @0(i64 %self, i8* %sel) {MainBlock: %0 = tail call i64 (i8*, i64, i8*, i8*, i8, i32, ...)* @rb_vm_dispatch(i8* inttoptr (i64 4309091648 to i8*), i64 %self, i8* inttoptr (i64 4308940784 to i8*), i8* null, i8 0, i32 1, i64 34360384192) ; <i64> [#uses=1] ret i64 %0}
declare i64 @rb_vm_dispatch(i8*, i64, i8*, i8*, i8, i32, ...)------------------------------------------------------
How the IR in LLVM looks?
MacRuby 0.5
Obj-C Runtime
GCC
LLVMJIT/AOT
Ruby Code
GC
Obj-C
Std LibApp
IO
Frameworks
One runtime
One object space
Shared infrastructure
Multithreaded
No GIL is needed.
MacRuby 0.5
MacRuby is not fully functional yet.Not installable around 85% RubySpecs passes.You can play with miniruby.
MacRuby 0.4
“Stable” version
Using Frameworks#import <Cocoa/Cocoa.h>
framework 'Cocoa'
Require a framework
Calling Obj-C Methods[dog makeNoise:@”wuff” level:6];
dog.makeNoise “wuff”, level:6
dog.makeNoise “wuff”, :level => 6
Defining Methods for Obj-C- (id) makeNoise:(NSString)noise level:(NSInteger)level;
def makeNoise(noise, level:level)
Using StructsNSPoint(0,1)
NSpoint.new(0,1)
PointerNSError* error;
//MacRuby 0.4error = Pointer.new_with_type('@')
//MacRuby 0.5error = Pointer.new(:object)
Pointers are often used as a means for output parameters, mostly for error handling.
alloc & init
[[NSMutableArray alloc] init]
Array.alloc.init == Array.new
Array.alloc.initWithArray([1])==Array.arrayWithArray([1])
Use Ruby from Objective-C//Possibleid dog = [NSClassFromString(@"Dog") new];[dog bark]
//Saferid dog = [[MacRuby sharedRuntime] evaluateString:@"Dog.new"];[dog performRubySelector: @selector(bark:)];
Ruby Parameters are always objects, careful when passing primitives!
XCode
MacRuby is supported in XCode.
Interface Builder
Also support by Interface Builder
Read this book to learn more about Interface Builder and XCode.
Interface Builder
Wire the GUI to your code.
OUTLETS
References to GUI elements
attr_writer :stalutation
attr_accessor :user_input
ACTIONS
Methods, which are supposed to be called on UI events.
def showSalutation(sender) @stalutation.stringValue = "Hi RailsWayCon!" end
Delegates
Specific to Ruby Cocoa and other frameworks.
def applicationDidFinishLoading(message) // do somehting here end
I am your delegate
Answer my Emails!
Alternative explanation: ActiveRecord callbacks with fixed names defined in another object.
With InterfaceBuilder you get very much, very fast, with very little code but rather static.Good for small Apps, prototypes, App parts.
More control, understanding, flexibility.
Hello World MacRubyframework 'Cocoa' app = NSApplication.sharedApplication window = NSWindow.alloc.initWithContentRect([0,0,200,60], styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask , backing:NSBackingStoreBuffered, defer:false) window.title = 'Hello World' label = NSTextField.alloc.initWithFrame(NSZeroRect)window.contentView.addSubview(label)label.stringValue = "Hello RailsWayCon!"label.setEditable(false)label.setSelectable(false)label.setBezeled(false)label.setDrawsBackground(false)label.sizeToFitlabel.frameOrigin = NSMakePoint((window.contentView.frameSize.width / 2) - (label.frameSize.width / 2)), (window.contentView.frameSize.height / 3))window.displaywindow.orderFrontRegardless app.run
No InterfaceBuilder -> lots of code
by: http://www.flickr.com/photos/myphotourl
HotCocoa. Not only a tasty drink but a smart Lib shipped with MacRuby.
HotCocoa
Ruby Wrapper for major frameworks
AppKit
WebKit
QtKit
CoreGraphics
CoreImage
HotCocoa
Constructors with smart defaults
Constants mapped to Symbols
Custom methods
Easy delegation
Constructors- Building the instances of the mapped classes using the correct class-specific APIs Smart Defaults - Default constructor parameters to minimize the needed parametersConstant Mapping - Use of Ruby symbols to minimize the text and incr. readabilityCustom Methods- Ruby-friendly API for commonly used methodsDelegate Methods - Ruby-friendly methods for delegating instances
Hello World HotCocoarequire 'hotcocoa'include HotCocoa application do window = window(title: 'Hello World', frame: [0,0,200,60]) label = label(text:'Hello RailsWayCon!', layout: {align::center}) window << labelend
Same App done with MacRuby.
\0_0/
Constructors with Smart Defaults
NSWindow.alloc.initWithContentRect([0,0,200,60], styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask , backing:NSBackingStoreBuffered, defer:false)
window(title: 'Hello World', frame: [0,0,200,60])
Constant Mappings
button.setBezelStyle(NSRoundedBezelStyle)
button.bezel = :rounded
Custom Methods
window.contentView.addSubview(label)
window << label
Delegate
button.target = selfbutton.action = 'sayHello'def sayHello p 'Hello!'end
botton.on_action {p 'Hello!'}
HotCoco Documentation
Soon
see /hotcocoa/mappings
HotConsole at gitHub to play arround
Lot of work to do to understand all available OS X frameworks.
So What?
The implications of MacRuby
Movement
?
Better Tool Support
!= Apple | XCode | InterfaceBuilder
HotCocoa, Rucola (App. Gen.)
HotConsole
Mature Testing Libraries
TestUnit (working)
Mocha (working)
Rspec
Shoulda
Cucumber (GUI manipulation?)
More applications for MAC!
Thanks
Start: macruby.org
Help: MacRuby-devel on MacOSForge
Twitter: @MacRuby
Thilo Utke 2009 for RailsWayConUpstream-Agile GmbH (upstream-berlin.com)