Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Objective-C vs. RubyMotion!

Objective-C vs. RubyMotion!

Presented at ChicagoRuby, Jan 8 2013.

David Demaree

January 08, 2013
Tweet

More Decks by David Demaree

Other Decks in Programming

Transcript

  1. VS
    OBJECTIVE-C RUBYMOTION

    View full-size slide

  2. David Demaree
    Typekit UX & Ruby engineer
    at Adobe
    @ddemaree
    log.demaree.me
    [email protected]



    View full-size slide

  3. Objective-C
    Invented in 1983, adopted by
    NeXT, currently maintained by
    Apple
    Pretty much used only for
    Apple platforms
    Statically typed object-
    oriented language
    Strict superset of C
    Preprocessed

    View full-size slide

  4. RubyMotion
    Implementation of Ruby 1.9
    (sort of) on LLVM and the
    Objective-C runtime
    Closed-source compiler,
    available commercially for $199
    (+ annual support fee)
    Open-source build tools, based
    on Rubygems and Rake

    View full-size slide

  5. WHY IS RUBYMOTION
    BETTER THAN ___?

    View full-size slide

  6. iOS Developer Agreement
    3.3.1 Applications may only use Documented APIs
    in the manner prescribed by Apple and must not
    use or call any private APIs. Applications must be
    originally written in Objective-C, C, C++, or JavaScript
    as executed by the iPhone OS WebKit engine, and only
    code written in C, C++, and Objective-C may compile
    and directly link against the Documented APIs (e.g.,
    Applications that link to Documented APIs through an
    intermediary translation or compatibility layer or tool
    are prohibited).

    View full-size slide

  7. iOS Developer Agreement
    3.3.1 Applications may only use Documented APIs
    in the manner prescribed by Apple and must not
    use or call any private APIs. Applications must be
    originally written in Objective-C, C, C++, or JavaScript
    as executed by the iPhone OS WebKit engine, and only
    code written in C, C++, and Objective-C may compile
    and directly link against the Documented APIs (e.g.,
    Applications that link to Documented APIs through an
    intermediary translation or compatibility layer or tool
    are prohibited).

    View full-size slide

  8. Ruby source code
    ObjC libraries
    Cocoa frameworks
    Native iOS app
    RubyMotion calls Cocoa frameworks directly

    View full-size slide

  9. PhoneGap app
    (HTML/CSS/JS)
    Objective-C
    runtime
    Cocoa app
    (Objective-C)
    Cocoa app
    (RubyMotion)
    Compiles to Obj-C bytecode
    Compiles to Obj-C bytecode
    PhoneGap
    cross-platform
    runtime

    View full-size slide

  10. 5by5.tv/hypercritical/66

    View full-size slide

  11. VS
    Objective-C Ruby syntax

    View full-size slide

  12. CAUTION
    Now entering nerd zone

    View full-size slide

  13. In the beginning, there was
    OBJECTIVE-C RUBY
    PYTHON
    JAVA SCALA
    GROOVY
    SMALLTALK

    View full-size slide

  14. Learning Objective-C
    Programming with
    Objective-‐C
    bit.ly/objcprimer apeth.com/iOSBook cocoabook.com

    View full-size slide

  15. Learning Ruby & RubyMotion
    All titles available at pragprog.com

    View full-size slide

  16. Statically compiled
    No require
    No eval
    No Proc#binding
    No define_method
    Named parameters
    RubyMotion
    !≈
    Ruby

    View full-size slide

  17. Classic Obj-C Modern Obj-C
    Brackets everywhere Properties & dot syntax
    Verbose code for working with
    basic object types
    Object literals
    Manual memory management ARC
    No blocks Blocks!

    View full-size slide

  18. Ruby can do almost
    anything Obj-C can do,
    BUT SIMPLER

    View full-size slide

  19. @interface DDVenue : NSObject
    @property (strong) NSString *name;
    @property (strong) NSString *address;
    @property (strong) CLLocation *location;
    - (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation;
    @end
    @implementation DDVenue
    @synthesize name, address, location;
    - (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation
    {
    return [self.location distanceFromLocation:otherLocation];
    }
    @end

    View full-size slide

  20. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end

    View full-size slide

  21. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end
    Everything inherits from (NS)Object

    View full-size slide

  22. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end
    Everything inherits from (NS)Object
    Dynamic/“duck” typing

    View full-size slide

  23. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end
    Everything inherits from (NS)Object
    Dynamic/“duck” typing
    Implicit return

    View full-size slide

  24. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end
    Everything inherits from (NS)Object
    Dynamic/“duck” typing
    Implicit return All dot syntax, all the time

    View full-size slide

  25. class Venue
    attr_accessor :name, :address, :location
    def distanceFromLocation(location)
    self.location.distanceFromLocation(location)
    end
    end
    Everything inherits from (NS)Object
    Dynamic/“duck” typing
    Implicit return All dot syntax, all the time
    No interface file required

    View full-size slide

  26. @interface DDFood : NSObject {
    BOOL isPizza;
    }
    - (void)setIsPizza:(BOOL)value;
    @end
    @implementation DDFood
    - (void)setIsPizza:(BOOL)value {
    isPizza = value;
    }
    @end
    class Food
    def isPizza=(pizzaness)
    @isPizza = pizzaness
    end
    def isPizza!
    @isPizza = true
    end
    def isPizza?
    @isPizza ||= false
    end
    end
    Instance vars must be declared Anything with an @-sigil is an ivar

    View full-size slide

  27. // YellingString.rb
    class String
    def yell
    self + "!"
    end
    end
    "Kind of awesome".yell.yell.yell
    #=> "Kind of awesome!!!"
    // NSString+Yelling.h
    @interface NSString (Yelling)
    - (NSString*) yell;
    @end
    // NSString+Yelling.m
    @implementation NSString (Yelling)
    - (NSString*) yell {
    return [self
    stringByAppendingString:@"!"];
    }
    @end
    [@"Kind of awesome" yell];
    //=> @"Kind of awesome!"
    Classes extended via categories Classes can be reopened at any time

    View full-size slide

  28. Ruby has real namespaces
    NSString, GBFont, DDCoreDataManager
    MyApp::Venue, MyApp::Item,
    CoreData::Manager
    Objective-C class names are prefixed
    Ruby classes/modules can be nested inside each other

    View full-size slide

  29. Multiple inheritance via mixins
    module StaticTableViewController
    CellInfo = Struct.new(:text, :accessory_type, :action)
    def tableView(tableView, cellForRowAtIndexPath:indexPath)
    cell = self.infoForCells[indexPath.row]
    # Create and return a UITableViewCell
    end
    end
    module SettingsViewController < UITableViewController
    include StaticTableViewController
    end

    View full-size slide

  30. class Thing < Struct.new(:name)
    def has_hat?
    false
    end
    end
    module Hat
    def has_hat?
    true
    end
    end

    View full-size slide

  31. myThing = Thing.new("Cat")
    myThing.has_hat? #=> false
    myThing.extend(Hat)
    myThing.has_hat? #=> true

    View full-size slide

  32. Blocks!
    class PlaceFinder
    def self.placeFinderWithBlock(&block)
    newFinder = self.alloc.init
    yield newFinder if block_given?
    return newFinder
    end
    end
    @finder = PlaceFinder.placeFinderWithBlock do |finder|
    finder.location = CLLocation.alloc.initWithLatitude(lat,
    longitude:lng)
    finder.numberOfResults = 10
    end

    View full-size slide

  33. HTTP.get("http://github.com/ddemaree") do |response|
    p response.body.to_str # prints the response's body
    end
    @singleton = nil
    Dispatch.once do
    @singleton ||= self.alloc.initWithOptions({})
    end
    Providing a completion callback for a HTTP request
    Initializing a singleton in a thread-safe way

    View full-size slide

  34. WHAT’S SO GREAT
    ABOUT SIMPLER?

    View full-size slide

  35. Less boilerplate

    View full-size slide

  36. Code is easier to read and
    more self-documenting

    View full-size slide

  37. It… feels good?

    View full-size slide

  38. What do we give up by
    using RubyMotion?

    View full-size slide

  39. No compile-time warnings

    View full-size slide

  40. No direct access to the C layer

    View full-size slide

  41. Enums and C structs
    typedef NS_ENUM(NSUInteger, GBListSettingsSection){
    GBListSettingsBudgetToggleSection,
    GBListSettingsSectionLock,
    GBListSettingsSectionEmail,
    GBListSettingsSectionAll
    };
    - (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section {
    if (section == GBListSettingsBudgetInclusionSection) {
    return 2;
    }
    }
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return GBListSettingsSectionAll;
    }

    View full-size slide

  42. class PlacesViewController < UITableViewController
    SECTIONS = [:budget, :lock, :email]
    def tableView(tableView, numberOfRowsInSection:section)
    sectionName = SECTIONS[section]
    if sectionName == :budget
    return 2
    end
    end
    def numberOfSectionsInTableView(tableView)
    SECTIONS.length
    end
    end

    View full-size slide

  43. The Uncanny Valley

    View full-size slide

  44. > motion ri UIView
    RubyMotion `ri` documentation

    View full-size slide

  45. RubyMotion’s “C” layer

    View full-size slide

  46. RubyMotion’s C-like APIs
    Dispatch.once { @singleton ||= self.new }
    errorPtr = Pointer.new(:object)
    ABAddressBookCreateWithOptions(nil, errorPtr)
    Pointers are objects
    Functions are wrapped as methods on the Object class
    Grand Central Dispatch is wrapped as the Dispatch module

    View full-size slide

  47. “Sexy” DSLs

    View full-size slide

  48. Covering all of Cocoa with newer,
    simpler DSL abstractions is a stated
    goal of RubyMotion’s creators

    View full-size slide

  49. alert = UIAlertView.alloc.initWithTitle "Hey, buddy",
    message: "Buzz off!",
    delegate: nil,
    cancelButtonTitle: nil,
    otherButtonTitles: nil
    alert.show()
    App.alert("Hey, buddy", message: "Buzz off!") do |alert|
    # You can perform any additional configuration on the
    # UIAlertView object here, using the `alert` variable
    end
    BubbleWrap
    Standard Cocoa API (in RubyMotion)

    View full-size slide

  50. github.com/alloy/MotionData

    View full-size slide

  51. PhoneGap app
    (HTML/CSS/JS)
    Objective-C
    runtime
    Cocoa app
    (Objective-C)
    Cocoa app
    (RubyMotion)
    Compiles to Obj-C bytecode
    PhoneGap
    cross-platform
    runtime
    RubyMotion
    DSLs?

    View full-size slide

  52. VS
    Bring your own Xcode

    View full-size slide

  53. VS
    Familiar (if you’re coming
    from Ruby/open-source
    development)
    Lighter-weight, which can
    be faster / more nimble
    Have it your way
    Supported by Apple
    Designed specifically for
    Cocoa/Cocoa Touch app
    development
    Excellent integrated
    documentation & code
    completion

    View full-size slide

  54. Xcode knows more about
    Cocoa & Objective-C than
    most of us will ever forget

    View full-size slide

  55. Context-sensitive code completion

    View full-size slide

  56. Integrated documentation

    View full-size slide

  57. Real-time error checking (via static analysis)

    View full-size slide

  58. “Using XCode is like driving a very used, modern car - it
    routinely breaks down, freezes and screws up the rest of my
    system and there is no way to understand what it wrong
    because all the parts are hidden from you. For example, it
    will stop compiling and simply freeze, acting like it's doing
    something. It will kill other processes and cause them to
    freeze (terminal processes simply stop getting cycles). It will
    stop responding to step over, step in, etc actions.
    “If there is any way for you to avoid XCode, do so. So far,
    I have had to force quit 4 times since 9:00 AM.”

    View full-size slide

  59. > motion create my_project

    View full-size slide

  60. Motion::Project::App.setup do |app|
    # Use `rake config' to see complete project settings.
    app.name = 'GiftBox'
    app.version = "2.0"
    app.interface_orientations = [:portrait]
    app.identifier = "me.demaree.GiftBox2"
    app.short_version = "190"
    app.frameworks += ["CoreData"]
    end
    RubyMotion configuration DSL

    View full-size slide

  61. github.com/mattt/shenzhen

    View full-size slide

  62. TESTING ON IOS

    View full-size slide

  63. Client-side applications
    are big, messy balls of
    SHARED STATE

    View full-size slide

  64. iOS client-side testing

    Full-stack JavaScript
    testing?

    View full-size slide

  65. Should I learn Cocoa on
    Objective-C first, or RubyMotion?

    View full-size slide

  66. Learn Objective-C
    Because it’s awesome (really)

    View full-size slide

  67. Learning Objective-C
    Programming with
    Objective-‐C
    bit.ly/objcprimer apeth.com/iOSBook cocoabook.com

    View full-size slide

  68. If you use RubyMotion, try to at
    least learn the Cocoa APIs

    View full-size slide

  69. Should I use RubyMotion?

    View full-size slide

  70. How I use RubyMotion today
    Personal projects
    Rapid prototyping
    Internal apps?

    View full-size slide

  71. Your questions

    View full-size slide

  72. David Demaree
    Typekit UX & Ruby engineer
    at Adobe
    @ddemaree
    log.demaree.me
    [email protected]



    View full-size slide