Rubymotion talk

Ignorance is Strength
           or

  How I Learned to Stop
 Worrying About XCode
and Objective-C and Learn
to Love iOS Development
Start
About Me

• Paul Infield-Harm
• Director of Product Development at Cyrus
  Innovation
• http://about.me/pinfieldharm
http://www.cyrusinnovation.com/
About you

• Ruby?
• Objective-C?
• iOS?
• RubyMotion?
What’s the point of this
         talk?
• I decided to try to learn RubyMotion
  without first learning traditional iOS
  development in XCode and Objective-C.
• If you’re starting out, you might be
  wondering how to start.
• A mix of experience report and tips-and-
  tricks
• This is also just about learning something
  new.
A way to learn

• Understand enough to make something,
  however messy
• Make it smaller
• Introduce third-party code
• Start over
Final Version
The final version
     system
http://markforster.squarespace.com/
Final Version system
•   Keep a list of tasks

•   Mark the first item with a dot

•   Go down the list until you find an item you want
    to do before the closest dotted item above

•   Repeat until you reach the end of the list

•   Then attend to the tasks in bottom-up order

•   Delete completed items, and otherwise move
    items to the end when you stop working on them

•   When nothing is left dotted, start dotting at the
    top again
Example
Write slides for meetup
Prepare TPS report
Get a haircut
Contemplate my mortality
Eat some ice cream
Example

• Write slides for meetup
  Prepare TPS report
• Get a haircut
  Contemplate my mortality
• Eat some ice cream
Example

• Write slides for meetup
  Prepare TPS report
• Get a haircut
  Contemplate my mortality
• Eat some ice cream
fv app
[demo]
RubyMotion
Here’s what some
rubymotion code looks
         like
fv source code

https://github.com/cyrusinnovation/fv
class TaskImageController < UIImagePickerController

  def viewDidLoad
    self.sourceType = has_camera? ? UIImagePickerControllerSourceTypeCamera :
UIImagePickerControllerSourceTypePhotoLibrary
    self.mediaTypes = [KUTTypeImage]
    self.delegate = self
    self.allowsImageEditing = false
  end

  def imagePickerControllerDidCancel(picker)
    presentingViewController.dismissModalViewControllerAnimated(true)
  end

  def imagePickerController(picker, didFinishPickingMediaWithInfo:info)
    mediaType = info[UIImagePickerControllerMediaType]
    TaskList.shared.add_photo_task(info[UIImagePickerControllerOriginalImage])
    presentingViewController.dismissModalViewControllerAnimated(true)
  end

  def has_camera?
    UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceTypeCamera)
  end

end
class TaskList
  TaskListChangedNotification = 'TaskListChanged'

  def self.shared
    @instance ||= TaskList.new
  end

  def all_tasks
    TaskStore.shared.all_tasks
  end

  def add_text_task(text)
    make_change do
      return if text == ''
      TaskStore.shared.create_task do |task|
        task.date_moved = NSDate.date
        task.text = text
        task.dotted = false
        task.active = false
        task.photo = false
      end
    end
  end

  def add_photo_task(image)
    make_change do
      TaskStore.shared.create_task do |task|
        task.date_moved = NSDate.date
        task.dotted = false
        task.active = false
        task.photo = true
        task.photo_uuid = BubbleWrap.create_uuid
        scaled_image = ImageStore.saveImage(image, forTask:task)
What is RubyMotion?

• Ruby re-implemented on top of iOS
• Ruby statically compiled
• Terminal-based toolchain
• Keep using your favorite editor
• Amazing community
(slide stolen from Laurent Sansonetti talk “RubyMotion: Ruby in your pocket” by Laurent Sansonett
                                via http://youtu.be/gG9GTUTI9ys)
How is it different from
         Ruby?
• added named arguments
• no eval
• no define_method
• no require
• most gems don’t work out of the box
Close-reading
Basic idea: Really
understand a working
RubyMotion program
Pierre Menard, Author
         of the Quixote

http://www.coldbacon.com/writing/borges-quixote.html
He did not want to compose another Quixote —which is easy— but the Quixote
itself. Needless to say, he never contemplated a mechanical transcription of the
original; he did not propose to copy it. His admirable intention was to produce a
few pages which would coincide—word for word and line for line—with those of
Miguel de Cervantes.

[...]

The first method he conceived was relatively simple. Know Spanish well, recover
the Catholic faith, fight against the Moors or the Turk, forget the history of Europe
between the years 1602 and 1918, be Miguel de Cervantes. Pierre Menard studied
this procedure (I know he attained a fairly accurate command of seventeenth-
century Spanish) but discarded it as too easy. Rather as impossible! my reader will
say. Granted, but the undertaking was impossible from the very beginning and of all
the impossible ways of carrying it out, this was the least interesting. To be, in the
twentieth century, a popular novelist of the seventeenth seemed to him a
diminution. To be, in some way, Cervantes and reach the Quixote seemed less
arduous to him—and, consequently, less interesting—than to go on being Pierre
Menard and reach the Quixote through the experiences of Pierre Menard.
Close-reading fv
[code]
Apple Developer docs

 http://developer.apple.com/library/IOs
Dash

http://kapeli.com/dash/
rubymotion.com docs

http://www.rubymotion.com/developer-center/
Translation
When you need to
      translate

• Making API calls
• Reading/using sample code
RubyMotion runtime
            guide
http://www.rubymotion.com/developer-center/guides/runtime/
Rewriting example:
 tableview code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TimeZoneCell";

    TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
    if (timeZoneCell == nil) {
        timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
        timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT);
    }
    Region *region = [displayList objectAtIndex:indexPath.section];
    NSArray *regionTimeZones = region.timeZoneWrappers;
    [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]];
    return timeZoneCell;
}




http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/TableViewCells/TableViewCells.html
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TimeZoneCell";

    TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
    if (timeZoneCell == nil) {
        timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
        timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT);
    }
    Region *region = [displayList objectAtIndex:indexPath.section];
    NSArray *regionTimeZones = region.timeZoneWrappers;
    [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]];
    return timeZoneCell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TimeZoneCell";

    TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
    if (timeZoneCell == nil) {
        timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
        timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT);
    }
    Region *region = [displayList objectAtIndex:indexPath.section];
    NSArray *regionTimeZones = region.timeZoneWrappers;
    [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]];
    return timeZoneCell;
}



CellIdentifier = "TimeZoneCell"
def tableView(tableView, cellForRowAtIndexPath:indexPath)
  timeZoneCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier)
  if (timeZoneCell == nil) {
    timeZoneCell = TimeZoneCell.alloc.initWithStyle(UITableViewCellStyleDefault,
reuseIdentifier:CellIdentifier)
    timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT)
  }
  region = displayList.objectAtIndex(indexPath.section)
  regionTimeZones = region.timeZoneWrappers
  timeZoneCell.setTimeZoneWrapper(regionTimeZones.objectAtIndex(indexPath.row))
  timeZoneCell
end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TimeZoneCell";

    TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
    if (timeZoneCell == nil) {
        timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
        timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT);
    }
    Region *region = [displayList objectAtIndex:indexPath.section];
    NSArray *regionTimeZones = region.timeZoneWrappers;
    [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]];
    return timeZoneCell;
}



CellIdentifier = "TimeZoneCell"
def tableView(tableView, cellForRowAtIndexPath:indexPath)
  timeZoneCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) || begin
    timeZoneCell = TimeZoneCell.alloc.initWithStyle(UITableViewCellStyleDefault,
reuseIdentifier:CellIdentifier)
    timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT)
    timeZoneCell
  end
  region = displayList[indexPath.section]
  regionTimeZones = region.timeZoneWrappers
  timeZoneCell.timeZoneWrapper = regionTimeZones[indexPath.row]
  timeZoneCell
end
About 30% reduction in
  code size, without
  much Rubification
This is as much
Objective-C as I
needed to know
Wrapper libraries
BubbleWrap
A collection of (tested) helpers and wrappers used to wrap
   CocoaTouch code and provide more Ruby like APIs.


                 http://bubblewrap.io/
addGestureRecognizer(UITapGestureRecognizer.alloc.initWithTarget(self, action:"handleTap"))
addGestureRecognizer(UISwipeGestureRecognizer.alloc.initWithTarget(self, action:"handleRightSwipe"))
leftRecognizer = UISwipeGestureRecognizer.alloc.initWithTarget(self, action:"handleLeftSwipe")
leftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft
addGestureRecognizer(leftRecognizer)


def handleTap
  TaskList.shared.toggle_dotted(taskID)
end

def handleRightSwipe
  TaskList.shared.remove_task(taskID) if @active
end

def handleLeftSwipe
  TaskList.shared.pause_task(taskID) if @active
end


                                          Before
              when_tapped { TaskList.shared.toggle_dotted(taskID) }
              when_swiped_right { TaskList.shared.remove_task(taskID) if @active }
              when_swiped_left { TaskList.shared.pause_task(taskID) if @active }



                                          After
sugarcube
a small library of extensions to the Ruby built-in classes that make it
a little easier - and hopefully more “rubyesque” - to work in Cocoa.



          https://github.com/rubymotion/sugarcube
Using other people’s
 objective-c code
Using third-party
        libraries

• vendoring
• cocoapods
Finding ios libraries

 http://www.cocoacontrols.com/
cocoapods
(go ye with caution)

http://cocoapods.org/
Getting help
Find someone who
knows more than you
RubyMotion Google
      Group

http://groups.google.com/group/rubymotion
Stack Overflow
My office hours

http://ohours.org/pinfieldharm
Thanks

http://www.slideshare.net/pinfieldharm/rubymotion-talk
1 of 55

Recommended

Sprockets by
SprocketsSprockets
SprocketsChristophe Porteneuve
12.2K views80 slides
Getting started with ES6 : Future of javascript by
Getting started with ES6 : Future of javascriptGetting started with ES6 : Future of javascript
Getting started with ES6 : Future of javascriptMohd Saeed
1K views34 slides
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014 by
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014Fábio Pimentel
2.1K views74 slides
Adding ES6 to Your Developer Toolbox by
Adding ES6 to Your Developer ToolboxAdding ES6 to Your Developer Toolbox
Adding ES6 to Your Developer ToolboxJeff Strauss
541 views124 slides
Es.next by
Es.nextEs.next
Es.nextIgnacio Gil
279 views58 slides
Modular JavaScript by
Modular JavaScriptModular JavaScript
Modular JavaScriptAndrew Eisenberg
2.6K views63 slides

More Related Content

Similar to Rubymotion talk

Refactor your way forward by
Refactor your way forwardRefactor your way forward
Refactor your way forwardJorge Ortiz
477 views69 slides
Implementing new WebAPIs by
Implementing new WebAPIsImplementing new WebAPIs
Implementing new WebAPIsJulian Viereck
1.6K views52 slides
Intro To Node.js by
Intro To Node.jsIntro To Node.js
Intro To Node.jsChris Cowan
13.7K views31 slides
Titanium Alloy Tutorial by
Titanium Alloy TutorialTitanium Alloy Tutorial
Titanium Alloy TutorialFokke Zandbergen
2.6K views69 slides
React nativebeginner1 by
React nativebeginner1React nativebeginner1
React nativebeginner1Oswald Campesato
447 views31 slides
iPhone dev intro by
iPhone dev introiPhone dev intro
iPhone dev introVonbo
708 views129 slides

Similar to Rubymotion talk(20)

Refactor your way forward by Jorge Ortiz
Refactor your way forwardRefactor your way forward
Refactor your way forward
Jorge Ortiz477 views
Intro To Node.js by Chris Cowan
Intro To Node.jsIntro To Node.js
Intro To Node.js
Chris Cowan13.7K views
iPhone dev intro by Vonbo
iPhone dev introiPhone dev intro
iPhone dev intro
Vonbo708 views
Beginning to iPhone development by Vonbo
Beginning to iPhone developmentBeginning to iPhone development
Beginning to iPhone development
Vonbo1.1K views
RubyMotion by Mark
RubyMotionRubyMotion
RubyMotion
Mark 2.4K views
MFF UK - Introduction to iOS by Petr Dvorak
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOS
Petr Dvorak807 views
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl... by Docker, Inc.
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
Docker, Inc.10.2K views
iPhone Camp Birmingham (Bham) - Intro To iPhone Development by andriajensen
iPhone Camp Birmingham (Bham) - Intro To iPhone DevelopmentiPhone Camp Birmingham (Bham) - Intro To iPhone Development
iPhone Camp Birmingham (Bham) - Intro To iPhone Development
andriajensen408 views
Android UI Tips, Tricks and Techniques by Marakana Inc.
Android UI Tips, Tricks and TechniquesAndroid UI Tips, Tricks and Techniques
Android UI Tips, Tricks and Techniques
Marakana Inc.4K views
Android UI Development: Tips, Tricks, and Techniques by Edgar Gonzalez
Android UI Development: Tips, Tricks, and TechniquesAndroid UI Development: Tips, Tricks, and Techniques
Android UI Development: Tips, Tricks, and Techniques
Edgar Gonzalez937 views
Dockercon EU 2014 by Rafe Colton
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014
Rafe Colton1.1K views
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba... by Sang Don Kim
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
Sang Don Kim883 views
I pad uicatalog_lesson02 by Rich Helton
I pad uicatalog_lesson02I pad uicatalog_lesson02
I pad uicatalog_lesson02
Rich Helton688 views
A tour on ruby and friends by 旻琦 潘
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘936 views
MFF UK - Advanced iOS Topics by Petr Dvorak
MFF UK - Advanced iOS TopicsMFF UK - Advanced iOS Topics
MFF UK - Advanced iOS Topics
Petr Dvorak1.1K views

Recently uploaded

Vertical User Stories by
Vertical User StoriesVertical User Stories
Vertical User StoriesMoisés Armani Ramírez
14 views16 slides
PRODUCT LISTING.pptx by
PRODUCT LISTING.pptxPRODUCT LISTING.pptx
PRODUCT LISTING.pptxangelicacueva6
14 views1 slide
"Running students' code in isolation. The hard way", Yurii Holiuk by
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk Fwdays
11 views34 slides
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf by
STKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdfSTKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdf
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdfDr. Jimmy Schwarzkopf
19 views29 slides
Special_edition_innovator_2023.pdf by
Special_edition_innovator_2023.pdfSpecial_edition_innovator_2023.pdf
Special_edition_innovator_2023.pdfWillDavies22
17 views6 slides
Data Integrity for Banking and Financial Services by
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial ServicesPrecisely
21 views26 slides

Recently uploaded(20)

"Running students' code in isolation. The hard way", Yurii Holiuk by Fwdays
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk
Fwdays11 views
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf by Dr. Jimmy Schwarzkopf
STKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdfSTKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdf
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf
Special_edition_innovator_2023.pdf by WillDavies22
Special_edition_innovator_2023.pdfSpecial_edition_innovator_2023.pdf
Special_edition_innovator_2023.pdf
WillDavies2217 views
Data Integrity for Banking and Financial Services by Precisely
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial Services
Precisely21 views
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas... by Bernd Ruecker
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
Bernd Ruecker37 views
Unit 1_Lecture 2_Physical Design of IoT.pdf by StephenTec
Unit 1_Lecture 2_Physical Design of IoT.pdfUnit 1_Lecture 2_Physical Design of IoT.pdf
Unit 1_Lecture 2_Physical Design of IoT.pdf
StephenTec12 views
SAP Automation Using Bar Code and FIORI.pdf by Virendra Rai, PMP
SAP Automation Using Bar Code and FIORI.pdfSAP Automation Using Bar Code and FIORI.pdf
SAP Automation Using Bar Code and FIORI.pdf
HTTP headers that make your website go faster - devs.gent November 2023 by Thijs Feryn
HTTP headers that make your website go faster - devs.gent November 2023HTTP headers that make your website go faster - devs.gent November 2023
HTTP headers that make your website go faster - devs.gent November 2023
Thijs Feryn22 views
STPI OctaNE CoE Brochure.pdf by madhurjyapb
STPI OctaNE CoE Brochure.pdfSTPI OctaNE CoE Brochure.pdf
STPI OctaNE CoE Brochure.pdf
madhurjyapb14 views

Rubymotion talk

  • 1. Ignorance is Strength or How I Learned to Stop Worrying About XCode and Objective-C and Learn to Love iOS Development
  • 3. About Me • Paul Infield-Harm • Director of Product Development at Cyrus Innovation • http://about.me/pinfieldharm
  • 5. About you • Ruby? • Objective-C? • iOS? • RubyMotion?
  • 6. What’s the point of this talk? • I decided to try to learn RubyMotion without first learning traditional iOS development in XCode and Objective-C. • If you’re starting out, you might be wondering how to start. • A mix of experience report and tips-and- tricks • This is also just about learning something new.
  • 7. A way to learn • Understand enough to make something, however messy • Make it smaller • Introduce third-party code • Start over
  • 9. The final version system http://markforster.squarespace.com/
  • 10. Final Version system • Keep a list of tasks • Mark the first item with a dot • Go down the list until you find an item you want to do before the closest dotted item above • Repeat until you reach the end of the list • Then attend to the tasks in bottom-up order • Delete completed items, and otherwise move items to the end when you stop working on them • When nothing is left dotted, start dotting at the top again
  • 11. Example Write slides for meetup Prepare TPS report Get a haircut Contemplate my mortality Eat some ice cream
  • 12. Example • Write slides for meetup Prepare TPS report • Get a haircut Contemplate my mortality • Eat some ice cream
  • 13. Example • Write slides for meetup Prepare TPS report • Get a haircut Contemplate my mortality • Eat some ice cream
  • 17. Here’s what some rubymotion code looks like
  • 19. class TaskImageController < UIImagePickerController def viewDidLoad self.sourceType = has_camera? ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary self.mediaTypes = [KUTTypeImage] self.delegate = self self.allowsImageEditing = false end def imagePickerControllerDidCancel(picker) presentingViewController.dismissModalViewControllerAnimated(true) end def imagePickerController(picker, didFinishPickingMediaWithInfo:info) mediaType = info[UIImagePickerControllerMediaType] TaskList.shared.add_photo_task(info[UIImagePickerControllerOriginalImage]) presentingViewController.dismissModalViewControllerAnimated(true) end def has_camera? UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceTypeCamera) end end
  • 20. class TaskList TaskListChangedNotification = 'TaskListChanged' def self.shared @instance ||= TaskList.new end def all_tasks TaskStore.shared.all_tasks end def add_text_task(text) make_change do return if text == '' TaskStore.shared.create_task do |task| task.date_moved = NSDate.date task.text = text task.dotted = false task.active = false task.photo = false end end end def add_photo_task(image) make_change do TaskStore.shared.create_task do |task| task.date_moved = NSDate.date task.dotted = false task.active = false task.photo = true task.photo_uuid = BubbleWrap.create_uuid scaled_image = ImageStore.saveImage(image, forTask:task)
  • 21. What is RubyMotion? • Ruby re-implemented on top of iOS • Ruby statically compiled • Terminal-based toolchain • Keep using your favorite editor • Amazing community (slide stolen from Laurent Sansonetti talk “RubyMotion: Ruby in your pocket” by Laurent Sansonett via http://youtu.be/gG9GTUTI9ys)
  • 22. How is it different from Ruby? • added named arguments • no eval • no define_method • no require • most gems don’t work out of the box
  • 24. Basic idea: Really understand a working RubyMotion program
  • 25. Pierre Menard, Author of the Quixote http://www.coldbacon.com/writing/borges-quixote.html
  • 26. He did not want to compose another Quixote —which is easy— but the Quixote itself. Needless to say, he never contemplated a mechanical transcription of the original; he did not propose to copy it. His admirable intention was to produce a few pages which would coincide—word for word and line for line—with those of Miguel de Cervantes. [...] The first method he conceived was relatively simple. Know Spanish well, recover the Catholic faith, fight against the Moors or the Turk, forget the history of Europe between the years 1602 and 1918, be Miguel de Cervantes. Pierre Menard studied this procedure (I know he attained a fairly accurate command of seventeenth- century Spanish) but discarded it as too easy. Rather as impossible! my reader will say. Granted, but the undertaking was impossible from the very beginning and of all the impossible ways of carrying it out, this was the least interesting. To be, in the twentieth century, a popular novelist of the seventeenth seemed to him a diminution. To be, in some way, Cervantes and reach the Quixote seemed less arduous to him—and, consequently, less interesting—than to go on being Pierre Menard and reach the Quixote through the experiences of Pierre Menard.
  • 29. Apple Developer docs http://developer.apple.com/library/IOs
  • 33. When you need to translate • Making API calls • Reading/using sample code
  • 34. RubyMotion runtime guide http://www.rubymotion.com/developer-center/guides/runtime/
  • 36. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"TimeZoneCell"; TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT); } Region *region = [displayList objectAtIndex:indexPath.section]; NSArray *regionTimeZones = region.timeZoneWrappers; [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]]; return timeZoneCell; } http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/TableViewCells/TableViewCells.html
  • 37. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"TimeZoneCell"; TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT); } Region *region = [displayList objectAtIndex:indexPath.section]; NSArray *regionTimeZones = region.timeZoneWrappers; [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]]; return timeZoneCell; }
  • 38. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"TimeZoneCell"; TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT); } Region *region = [displayList objectAtIndex:indexPath.section]; NSArray *regionTimeZones = region.timeZoneWrappers; [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]]; return timeZoneCell; } CellIdentifier = "TimeZoneCell" def tableView(tableView, cellForRowAtIndexPath:indexPath) timeZoneCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) if (timeZoneCell == nil) { timeZoneCell = TimeZoneCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:CellIdentifier) timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT) } region = displayList.objectAtIndex(indexPath.section) regionTimeZones = region.timeZoneWrappers timeZoneCell.setTimeZoneWrapper(regionTimeZones.objectAtIndex(indexPath.row)) timeZoneCell end
  • 39. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"TimeZoneCell"; TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT); } Region *region = [displayList objectAtIndex:indexPath.section]; NSArray *regionTimeZones = region.timeZoneWrappers; [timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]]; return timeZoneCell; } CellIdentifier = "TimeZoneCell" def tableView(tableView, cellForRowAtIndexPath:indexPath) timeZoneCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) || begin timeZoneCell = TimeZoneCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:CellIdentifier) timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT) timeZoneCell end region = displayList[indexPath.section] regionTimeZones = region.timeZoneWrappers timeZoneCell.timeZoneWrapper = regionTimeZones[indexPath.row] timeZoneCell end
  • 40. About 30% reduction in code size, without much Rubification
  • 41. This is as much Objective-C as I needed to know
  • 43. BubbleWrap A collection of (tested) helpers and wrappers used to wrap CocoaTouch code and provide more Ruby like APIs. http://bubblewrap.io/
  • 44. addGestureRecognizer(UITapGestureRecognizer.alloc.initWithTarget(self, action:"handleTap")) addGestureRecognizer(UISwipeGestureRecognizer.alloc.initWithTarget(self, action:"handleRightSwipe")) leftRecognizer = UISwipeGestureRecognizer.alloc.initWithTarget(self, action:"handleLeftSwipe") leftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft addGestureRecognizer(leftRecognizer) def handleTap TaskList.shared.toggle_dotted(taskID) end def handleRightSwipe TaskList.shared.remove_task(taskID) if @active end def handleLeftSwipe TaskList.shared.pause_task(taskID) if @active end Before when_tapped { TaskList.shared.toggle_dotted(taskID) } when_swiped_right { TaskList.shared.remove_task(taskID) if @active } when_swiped_left { TaskList.shared.pause_task(taskID) if @active } After
  • 45. sugarcube a small library of extensions to the Ruby built-in classes that make it a little easier - and hopefully more “rubyesque” - to work in Cocoa. https://github.com/rubymotion/sugarcube
  • 46. Using other people’s objective-c code
  • 47. Using third-party libraries • vendoring • cocoapods
  • 48. Finding ios libraries http://www.cocoacontrols.com/
  • 49. cocoapods (go ye with caution) http://cocoapods.org/
  • 51. Find someone who knows more than you
  • 52. RubyMotion Google Group http://groups.google.com/group/rubymotion

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n