Rubymotion talk
Upcoming SlideShare
Loading in...5
×
 

Rubymotion talk

on

  • 763 views

Presentation slides for NYC RubyMotion meetup (http://www.meetup.com/NYC-RubyMotion/events/78151782/)

Presentation slides for NYC RubyMotion meetup (http://www.meetup.com/NYC-RubyMotion/events/78151782/)

Statistics

Views

Total Views
763
Views on SlideShare
763
Embed Views
0

Actions

Likes
3
Downloads
5
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Rubymotion talk Rubymotion talk Presentation Transcript

  • Ignorance is Strength or How I Learned to Stop Worrying About XCodeand Objective-C and Learnto 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 systemhttp://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
  • ExampleWrite slides for meetupPrepare TPS reportGet a haircutContemplate my mortalityEat 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 somerubymotion code looks like
  • fv source codehttps://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) endend
  • 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: Reallyunderstand a workingRubyMotion program
  • Pierre Menard, Author of the Quixotehttp://www.coldbacon.com/writing/borges-quixote.html
  • He did not want to compose another Quixote —which is easy— but the Quixoteitself. Needless to say, he never contemplated a mechanical transcription of theoriginal; he did not propose to copy it. His admirable intention was to produce afew pages which would coincide—word for word and line for line—with those ofMiguel de Cervantes.[...]The first method he conceived was relatively simple. Know Spanish well, recoverthe Catholic faith, fight against the Moors or the Turk, forget the history of Europebetween the years 1602 and 1918, be Miguel de Cervantes. Pierre Menard studiedthis procedure (I know he attained a fairly accurate command of seventeenth-century Spanish) but discarded it as too easy. Rather as impossible! my reader willsay. Granted, but the undertaking was impossible from the very beginning and of allthe impossible ways of carrying it out, this was the least interesting. To be, in thetwentieth century, a popular novelist of the seventeenth seemed to him adiminution. To be, in some way, Cervantes and reach the Quixote seemed lessarduous to him—and, consequently, less interesting—than to go on being PierreMenard and reach the Quixote through the experiences of Pierre Menard.
  • Close-reading fv
  • [code]
  • Apple Developer docs http://developer.apple.com/library/IOs
  • Dashhttp://kapeli.com/dash/
  • rubymotion.com docshttp://www.rubymotion.com/developer-center/
  • Translation
  • When you need to translate• Making API calls• Reading/using sample code
  • RubyMotion runtime guidehttp://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 *)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier: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 *)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier: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 *)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier: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)) timeZoneCellend
  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"TimeZoneCell"; TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier]; if (timeZoneCell == nil) { timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier: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] timeZoneCellend
  • About 30% reduction in code size, without much Rubification
  • This is as muchObjective-C as Ineeded to know
  • Wrapper libraries
  • BubbleWrapA 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 = UISwipeGestureRecognizerDirectionLeftaddGestureRecognizer(leftRecognizer)def handleTap TaskList.shared.toggle_dotted(taskID)enddef handleRightSwipe TaskList.shared.remove_task(taskID) if @activeenddef handleLeftSwipe TaskList.shared.pause_task(taskID) if @activeend 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
  • sugarcubea small library of extensions to the Ruby built-in classes that make ita 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 whoknows more than you
  • RubyMotion Google Grouphttp://groups.google.com/group/rubymotion
  • Stack Overflow
  • My office hourshttp://ohours.org/pinfieldharm
  • Thankshttp://www.slideshare.net/pinfieldharm/rubymotion-talk