Objective-C vs. RubyMotion!

Objective-C vs. RubyMotion!

Presented at ChicagoRuby, Jan 8 2013.

C157b16234f1e75e8eac3698c1d4414a?s=128

David Demaree

January 08, 2013
Tweet

Transcript

  1. None
  2. VS OBJECTIVE-C RUBYMOTION

  3. David Demaree Typekit UX & Ruby engineer at Adobe @ddemaree

    log.demaree.me ddemaree@gmail.com   ✉
  4. 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
  5. 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
  6. WHY IS RUBYMOTION BETTER THAN ___?

  7. None
  8. None
  9. 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).
  10. 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).
  11. Ruby source code ObjC libraries Cocoa frameworks Native iOS app

    RubyMotion calls Cocoa frameworks directly
  12. 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
  13. Apple

  14. 5by5.tv/hypercritical/66

  15. CODE

  16. VS Objective-C Ruby syntax

  17. CAUTION Now entering nerd zone

  18. In the beginning, there was OBJECTIVE-C RUBY PYTHON JAVA SCALA

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

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

  21. Statically compiled No require No eval No Proc#binding No define_method

    Named parameters RubyMotion !≈ Ruby
  22. Objective-C

  23. 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!
  24. Objective-C

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

  26. @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
  27. class Venue attr_accessor :name, :address, :location def distanceFromLocation(location) self.location.distanceFromLocation(location) end

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

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

    end Everything inherits from (NS)Object Dynamic/“duck” typing
  30. 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
  31. 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
  32. 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
  33. @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
  34. // 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
  35. 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
  36. 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
  37. class Thing < Struct.new(:name) def has_hat? false end end module

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

  39. 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
  40. 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
  41. WHAT’S SO GREAT ABOUT SIMPLER?

  42. Less boilerplate

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

  44. It… feels good?

  45. What do we give up by using RubyMotion?

  46. No compile-time warnings

  47. No direct access to the C layer

  48. 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; }
  49. 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
  50. The Uncanny Valley

  51. > motion ri UIView RubyMotion `ri` documentation

  52. RubyMotion’s “C” layer

  53. 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
  54. “Sexy” DSLs

  55. Covering all of Cocoa with newer, simpler DSL abstractions is

    a stated goal of RubyMotion’s creators
  56. None
  57. 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)
  58. github.com/alloy/MotionData

  59. 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?
  60. TOOLS

  61. VS Bring your own Xcode

  62. 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
  63. Xcode knows more about Cocoa & Objective-C than most of

    us will ever forget
  64. Context-sensitive code completion

  65. Integrated documentation

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

  67. “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.”
  68. better? Is

  69. > motion create my_project

  70. 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
  71. None
  72. None
  73. None
  74. github.com/mattt/shenzhen

  75. TESTING

  76. TESTING ON IOS

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

  78. iOS client-side testing ≈ Full-stack JavaScript testing?

  79. QUESTIONS

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

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

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

  83. None
  84. If you use RubyMotion, try to at least learn the

    Cocoa APIs
  85. Should I use RubyMotion?

  86. How I use RubyMotion today Personal projects Rapid prototyping Internal

    apps?
  87. Your questions

  88. David Demaree Typekit UX & Ruby engineer at Adobe @ddemaree

    log.demaree.me ddemaree@gmail.com   ✉