SlideShare ist ein Scribd-Unternehmen logo
1 von 76
RubyMotion
iOS Development with Ruby
      @markbates
I HATE iOS
DEVELOPMENT!
Why I Hate iOS Development
Why I Hate iOS Development

✦   XCode
Why I Hate iOS Development

✦   XCode
✦   Objective-C
Why I Hate iOS Development

✦   XCode
✦   Objective-C
✦   Cocoa/iOS APIs
XCode
Objective-C
# Create a new array (mutable):
myArray = %w{hello world etc}
myArray << "new value"

# Create a new hash (mutable):
myHash = {"key-a" => "value-a", "key-b" => "value-b"}
myHash["key-c"] = "value-c"
// Create a new array:
NSArray *myArray = [NSArray arrayWithObjects:@"hello",@"world",@"etc",nil];

// Create a mutable array:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
[myArray addObject:@"hello world"];

// Create a dictionary (hash):
NSDictionary *myDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
@"value-a", @"key-a", @"value-b", @"key-b", nil];

// Create a mutable dictionary:
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary];
[myDictionary setObject: @"value-c" forKey: @"key-c"];
now = -> {
  puts "The date and time is: #{Time.now}"
}

now.call
void (^now)(void) = ^ {
  NSDate *date = [NSDate date];
  NSLog(@"The date and time is %@", date);
};

now();
Cocoa/iOS APIs
require 'net/http'
require 'json'

url = "http://www.example.com/api.json"
response = Net::HTTP.get_response(URI.parse(url))

if response.code.to_i == 200
  json = JSON.parse(response.body)
  puts json.inspect
else
  puts "An Error Occurred (#{response.code}): #{response.body}"
end
- (void)viewDidLoad {
  [super viewDidLoad];
  responseData = [[NSMutableData data] retain];
  NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com/api.json"]];
  [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  [responseData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  [responseData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
  label.text = [NSString stringWithFormat:@"Connection failed: %@", [error description]];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  [connection release];

  NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
  [responseData release];
  
  NSError *error;
  SBJSON *json = [[SBJSON new] autorelease];
  NSArray *myArray = [json objectWithString:responseString error:&error];
  [responseString release];
  
  if (myArray == nil)
    label.text = [NSString stringWithFormat:@"JSON parsing failed: %@", [error localizedDescription]];
  else {
    NSMutableString *text = [NSMutableString stringWithString:@"Array Data:n"];
    
    for (int i = 0; i < [myArray count]; i++)
      [text appendFormat:@"%@n", [myArray objectAtIndex:i]];

    label.text =   text;
  }
}
Laurent Sansonetti

✦   Worked for Apple for 7 years on iLife and
    OS X

✦   Developed MacRuby

✦   Developed RubyCocoa

✦   Belgian
So What Does it Do?
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)

✦   Keep Your Editor (NO XCODE!)
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)

✦   Keep Your Editor (NO XCODE!)

✦   IRB
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)

✦   Keep Your Editor (NO XCODE!)

✦   IRB

✦   Terminal Based Workflow (Rake)
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)

✦   Keep Your Editor (NO XCODE!)

✦   IRB

✦   Terminal Based Workflow (Rake)

✦   Testing Framework (MacBacon)
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)       ✦   Native Applications

✦   Keep Your Editor (NO XCODE!)

✦   IRB

✦   Terminal Based Workflow (Rake)

✦   Testing Framework (MacBacon)
So What Does it Do?
✦   Ruby!!! (NO OBJECTIVE-C!)       ✦   Native Applications

✦   Keep Your Editor (NO XCODE!)    ✦   App Store Approved

✦   IRB

✦   Terminal Based Workflow (Rake)

✦   Testing Framework (MacBacon)
Suck it Objective-C!
NSString *urlAsString = @"http://www.apple.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[NSURLConnection
 sendAsynchronousRequest:urlRequest
 queue:queue
 completionHandler:^(NSURLResponse *response,
                     NSData *data,
                     NSError *error) {
   
   if ([data length] >0 &&
       error == nil){
     
     /* Get the documents directory */
     NSString *documentsDir =
     [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                          NSUserDomainMask,
                                          YES) objectAtIndex:0];
     
     /* Append the file name to the documents directory */
     NSString *filePath = [documentsDir
                           stringByAppendingPathComponent:@"apple.html"];
     
     /* Write the data to the file */
     [data writeToFile:filePath
            atomically:YES];
     
     NSLog(@"Successfully saved the file to %@", filePath);
     
   }
   else if ([data length] == 0 &&
            error == nil){
     NSLog(@"Nothing was downloaded.");
   }
   else if (error != nil){
     NSLog(@"Error happened = %@", error);
   }
   
 }];
url = NSURL.URLWithString("http://www.apple.com")
request = NSURLRequest.requestWithURL(url)
queue = NSOperationQueue.alloc.init

NSURLConnection.sendAsynchronousRequest(request,
  queue: queue,
  completionHandler: lambda do |response, data, error|
    if(data.length > 0 && error.nil?)
      doc_dir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                    NSUserDomainMask,
                                                    true).first
      #p doc_dir
      file_path = doc_dir.stringByAppendingPathComponent("apple.html")

      data.writeToFile(file_path, atomically: true)

      p "Saved file to #{file_path}"
    elsif( data.length == 0 && error.nil? )
      p "Nothing was downloaded"
    elsif(!error.nil?)
      p "Error: #{error}"
    end
  end)
But What About Those Weird
Named Argument Methods?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  // do something
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  // do something
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  // do something
}
def tableView(tableView, didSelectRowAtIndexPath: indexPath)
  # do something
end

def tableView(tableView, numberOfRowsInSection: section)
  # do something
end

def tableView(tableView, cellForRowAtIndexPath: indexPath)
  # do something
end
Demo Time
Bubble Wrap
https://github.com/rubymotion/BubbleWrap
HTTP
data = {first_name: 'Matt', last_name: 'Aimonetti'}
BubbleWrap::HTTP.post("http://foo.bar.com/", {payload: data}) do |response|
 if response.ok?
   json = BubbleWrap::JSON.parse(response.body.to_str)
   p json['id']
 elsif response.status_code.to_s =~ /40d/
   App.alert("Login failed")
 else
   App.alert(response.error_message)
 end
end
App
> App.documents_path
# "~/iPhone Simulator/5.0/Applications/EEC6454E-1816-451E-BB9A-EE18222E1A8F/Documents"
> App.resources_path
# "~/iPhone Simulator/5.0/Applications/EEC64-1816-451E-BB9A-EE18221A8F/testSuite_spec.app"
> App.name
# "testSuite"
> App.identifier
# "io.bubblewrap.testSuite"
> App.alert("BubbleWrap is awesome!")
# creates and shows an alert message.
> App.run_after(0.5) { p "It's #{Time.now}" }
# Runs the block after 0.5 seconds.
> App.open_url("http://matt.aimonetti.net")
# Opens the url using the device's browser. (accepts a string url or an instance of NSURL.
> App::Persistence['channels'] # application specific persistence storage
# ['NBC', 'ABC', 'Fox', 'CBS', 'PBS']
> App::Persistence['channels'] = ['TF1', 'France 2', 'France 3']
# ['TF1', 'France 2', 'France 3']
Device
> Device.iphone?
# true
> Device.ipad?
# false
> Device.front_camera?
# true
> Device.rear_camera?
# true
> Device.orientation
# :portrait
> Device.simulator?
# true
> Device.retina?
# false
> Device.screen.width
# 320
> Device.screen.height
# 480
> Device.screen.width_for_orientation(:landscape_left)
# 480
> Device.screen.height_for_orientation(:landscape_left)
# 320
Camera
# Uses the front camera
BW::Device.camera.front.picture(media_types: [:movie, :image]) do |result|
 image_view = UIImageView.alloc.initWithImage(result[:original_image])
end

# Uses the rear camera
BW::Device.camera.rear.picture(media_types: [:movie, :image]) do |result|
 image_view = UIImageView.alloc.initWithImage(result[:original_image])
end

# Uses the photo library
BW::Device.camera.any.picture(media_types: [:movie, :image]) do |result|
 image_view = UIImageView.alloc.initWithImage(result[:original_image])
end
JSON

BW::JSON.generate({'foo => 1, 'bar' => [1,2,3], 'baz => 'awesome'})
=> "{"foo":1,"bar":[1,2,3],"baz":"awesome"}"
BW::JSON.parse "{"foo":1,"bar":[1,2,3],"baz":"awesome"}"
=> {"foo"=>1, "bar"=>[1, 2, 3], "baz"=>"awesome"}
Media

# Plays in your custom frame
local_file = NSURL.fileURLWithPath(File.join(NSBundle.mainBundle.resourcePath, 'test.mp3'))
BW::Media.play(local_file) do |media_player|
  media_player.view.frame = [[10, 100], [100, 100]]
  self.view.addSubview media_player.view
end

# Plays in an independent modal controller
BW::Media.play_modal("http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3")
Deferrables
> d = EM::DefaultDeferrable.new
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x6d859a0>
> d.callback { |what| puts "Great #{what}!" }
=> [#<Proc:0x6d8a1e0>]
> d.succeed "justice"
Great justice!
=> nil
Events
> o = Class.new { include EM::Eventable }.new
=> #<#<Class:0x6dc1310>:0x6dc2ec0>
> o.on(:november_5_1955) { puts "Ow!" }
=> [#<Proc:0x6dc6300>]
> o.on(:november_5_1955) { puts "Flux capacitor!" }
=> [#<Proc:0x6dc6300>, #<Proc:0x6dc1ba0>]
> o.trigger(:november_5_1955)
Ow!
Flux capacitor!
=> [nil, nil]
More...
✦   Localization                            ✦   Location

✦   Color                                   ✦   Gestures

✦   UUID Generator                          ✦   RSS Parser

✦   NSNotificationCenter                     ✦   Reactor

✦   Persistence                             ✦   Timers

✦   Observers

✦   String (underscore, camelize, etc...)
Pros & Cons
The Pros
The Pros
✦   Ruby!!
The Pros
✦   Ruby!!

✦   IDE Agnostic
The Pros
✦   Ruby!!

✦   IDE Agnostic

✦   “Wrapper” Gems
The Pros
✦   Ruby!!

✦   IDE Agnostic

✦   “Wrapper” Gems

✦   Fast
The Pros
✦   Ruby!!

✦   IDE Agnostic

✦   “Wrapper” Gems

✦   Fast

✦   IRB
The Pros
✦   Ruby!!               ✦   Easy to test

✦   IDE Agnostic

✦   “Wrapper” Gems

✦   Fast

✦   IRB
The Pros
✦   Ruby!!               ✦   Easy to test

✦   IDE Agnostic         ✦   Growing community

✦   “Wrapper” Gems

✦   Fast

✦   IRB
The Pros
✦   Ruby!!               ✦   Easy to test

✦   IDE Agnostic         ✦   Growing community

✦   “Wrapper” Gems       ✦   Frequent updates

✦   Fast

✦   IRB
The Cons
The Cons
✦   Cost - $199
The Cons
✦   Cost - $199

✦   Existing tutorials in Objective-C
The Cons
✦   Cost - $199

✦   Existing tutorials in Objective-C

✦   Maintainability?
The Cons
✦   Cost - $199

✦   Existing tutorials in Objective-C

✦   Maintainability?

✦   No Debugger (Yet)
The Cons
✦   Cost - $199

✦   Existing tutorials in Objective-C

✦   Maintainability?

✦   No Debugger (Yet)

✦   Difficult to work with Interface Builder
The Verdict
Resources
✦   http://www.rubymotion.com            ✦   http://rubymotionapps.com/projects

✦   http://rubymotion-tutorial.com       ✦   http://pragmaticstudio.com/screencasts/
                                             rubymotion
✦   https://github.com/IconoclastLabs/
    rubymotion_cookbook

✦   https://github.com/railsfactory/
    rubymotion-cookbook

✦   https://twitter.com/RubyMotion

✦   http://rubymotionweekly.com

Weitere ähnliche Inhalte

Was ist angesagt?

The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le WagonAlex Benoit
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND Enrique Oriol Bermúdez
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...Codemotion
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, BadooYandex
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.jsJay Phelps
 
Javascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyJavascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyThorsten Suckow-Homberg
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IVisual Engineering
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
Bee Smalltalk RunTime: anchor's aweigh
Bee Smalltalk RunTime: anchor's aweighBee Smalltalk RunTime: anchor's aweigh
Bee Smalltalk RunTime: anchor's aweighESUG
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)James Titcumb
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)James Titcumb
 

Was ist angesagt? (20)

Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le Wagon
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.js
 
What's new in iOS9
What's new in iOS9What's new in iOS9
What's new in iOS9
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
Javascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyJavascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the Ugly
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
Bee Smalltalk RunTime: anchor's aweigh
Bee Smalltalk RunTime: anchor's aweighBee Smalltalk RunTime: anchor's aweigh
Bee Smalltalk RunTime: anchor's aweigh
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
 
YQL & Yahoo! Apis
YQL & Yahoo! ApisYQL & Yahoo! Apis
YQL & Yahoo! Apis
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
 

Ähnlich wie RubyMotion

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Mac ruby to the max - Brendan G. Lim
Mac ruby to the max - Brendan G. LimMac ruby to the max - Brendan G. Lim
Mac ruby to the max - Brendan G. LimThoughtWorks
 
MacRuby to The Max
MacRuby to The MaxMacRuby to The Max
MacRuby to The MaxBrendan Lim
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerNic Raboy
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Ruby MVC from scratch with Rack
Ruby MVC from scratch with RackRuby MVC from scratch with Rack
Ruby MVC from scratch with RackDonSchado
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on AndroidSven Haiges
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineRicardo Silva
 
PySpark with Juypter
PySpark with JuypterPySpark with Juypter
PySpark with JuypterLi Ming Tsai
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011Nick Sieger
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with RubyAnis Ahmad
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentanistar sung
 
Meetup uikit programming
Meetup uikit programmingMeetup uikit programming
Meetup uikit programmingjoaopmaia
 
Front End Development: The Important Parts
Front End Development: The Important PartsFront End Development: The Important Parts
Front End Development: The Important PartsSergey Bolshchikov
 

Ähnlich wie RubyMotion (20)

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
mobl
moblmobl
mobl
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Mac ruby to the max - Brendan G. Lim
Mac ruby to the max - Brendan G. LimMac ruby to the max - Brendan G. Lim
Mac ruby to the max - Brendan G. Lim
 
MacRuby to The Max
MacRuby to The MaxMacRuby to The Max
MacRuby to The Max
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase Server
 
JavaScript ES6
JavaScript ES6JavaScript ES6
JavaScript ES6
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Ruby MVC from scratch with Rack
Ruby MVC from scratch with RackRuby MVC from scratch with Rack
Ruby MVC from scratch with Rack
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
Intro to appcelerator
Intro to appceleratorIntro to appcelerator
Intro to appcelerator
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 Engine
 
PySpark with Juypter
PySpark with JuypterPySpark with Juypter
PySpark with Juypter
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
 
Meetup uikit programming
Meetup uikit programmingMeetup uikit programming
Meetup uikit programming
 
Front End Development: The Important Parts
Front End Development: The Important PartsFront End Development: The Important Parts
Front End Development: The Important Parts
 

Mehr von Mark

Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web AppsMark
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js FundamentalsMark
 
Go(lang) for the Rubyist
Go(lang) for the RubyistGo(lang) for the Rubyist
Go(lang) for the RubyistMark
 
Mangling Ruby with TracePoint
Mangling Ruby with TracePointMangling Ruby with TracePoint
Mangling Ruby with TracePointMark
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsMark
 
A Big Look at MiniTest
A Big Look at MiniTestA Big Look at MiniTest
A Big Look at MiniTestMark
 
A Big Look at MiniTest
A Big Look at MiniTestA Big Look at MiniTest
A Big Look at MiniTestMark
 
GET /better
GET /betterGET /better
GET /betterMark
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScriptMark
 
Testing Your JavaScript & CoffeeScript
Testing Your JavaScript & CoffeeScriptTesting Your JavaScript & CoffeeScript
Testing Your JavaScript & CoffeeScriptMark
 
Building an API in Rails without Realizing It
Building an API in Rails without Realizing ItBuilding an API in Rails without Realizing It
Building an API in Rails without Realizing ItMark
 
5 Favorite Gems (Lightning Talk(
5 Favorite Gems (Lightning Talk(5 Favorite Gems (Lightning Talk(
5 Favorite Gems (Lightning Talk(Mark
 
CoffeeScript for the Rubyist
CoffeeScript for the RubyistCoffeeScript for the Rubyist
CoffeeScript for the RubyistMark
 
Testing JavaScript/CoffeeScript with Mocha and Chai
Testing JavaScript/CoffeeScript with Mocha and ChaiTesting JavaScript/CoffeeScript with Mocha and Chai
Testing JavaScript/CoffeeScript with Mocha and ChaiMark
 
CoffeeScript for the Rubyist
CoffeeScript for the RubyistCoffeeScript for the Rubyist
CoffeeScript for the RubyistMark
 
Testing Rich Client Side Apps with Jasmine
Testing Rich Client Side Apps with JasmineTesting Rich Client Side Apps with Jasmine
Testing Rich Client Side Apps with JasmineMark
 
DRb and Rinda
DRb and RindaDRb and Rinda
DRb and RindaMark
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairMark
 
Distributed Programming with Ruby/Rubyconf 2010
Distributed Programming with Ruby/Rubyconf 2010Distributed Programming with Ruby/Rubyconf 2010
Distributed Programming with Ruby/Rubyconf 2010Mark
 

Mehr von Mark (19)

Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web Apps
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
Go(lang) for the Rubyist
Go(lang) for the RubyistGo(lang) for the Rubyist
Go(lang) for the Rubyist
 
Mangling Ruby with TracePoint
Mangling Ruby with TracePointMangling Ruby with TracePoint
Mangling Ruby with TracePoint
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.js
 
A Big Look at MiniTest
A Big Look at MiniTestA Big Look at MiniTest
A Big Look at MiniTest
 
A Big Look at MiniTest
A Big Look at MiniTestA Big Look at MiniTest
A Big Look at MiniTest
 
GET /better
GET /betterGET /better
GET /better
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Testing Your JavaScript & CoffeeScript
Testing Your JavaScript & CoffeeScriptTesting Your JavaScript & CoffeeScript
Testing Your JavaScript & CoffeeScript
 
Building an API in Rails without Realizing It
Building an API in Rails without Realizing ItBuilding an API in Rails without Realizing It
Building an API in Rails without Realizing It
 
5 Favorite Gems (Lightning Talk(
5 Favorite Gems (Lightning Talk(5 Favorite Gems (Lightning Talk(
5 Favorite Gems (Lightning Talk(
 
CoffeeScript for the Rubyist
CoffeeScript for the RubyistCoffeeScript for the Rubyist
CoffeeScript for the Rubyist
 
Testing JavaScript/CoffeeScript with Mocha and Chai
Testing JavaScript/CoffeeScript with Mocha and ChaiTesting JavaScript/CoffeeScript with Mocha and Chai
Testing JavaScript/CoffeeScript with Mocha and Chai
 
CoffeeScript for the Rubyist
CoffeeScript for the RubyistCoffeeScript for the Rubyist
CoffeeScript for the Rubyist
 
Testing Rich Client Side Apps with Jasmine
Testing Rich Client Side Apps with JasmineTesting Rich Client Side Apps with Jasmine
Testing Rich Client Side Apps with Jasmine
 
DRb and Rinda
DRb and RindaDRb and Rinda
DRb and Rinda
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love Affair
 
Distributed Programming with Ruby/Rubyconf 2010
Distributed Programming with Ruby/Rubyconf 2010Distributed Programming with Ruby/Rubyconf 2010
Distributed Programming with Ruby/Rubyconf 2010
 

Kürzlich hochgeladen

Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 

Kürzlich hochgeladen (20)

Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 

RubyMotion

  • 2.
  • 3.
  • 5. Why I Hate iOS Development
  • 6. Why I Hate iOS Development ✦ XCode
  • 7. Why I Hate iOS Development ✦ XCode ✦ Objective-C
  • 8. Why I Hate iOS Development ✦ XCode ✦ Objective-C ✦ Cocoa/iOS APIs
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18. XCode
  • 19.
  • 20.
  • 21.
  • 22.
  • 24. # Create a new array (mutable): myArray = %w{hello world etc} myArray << "new value" # Create a new hash (mutable): myHash = {"key-a" => "value-a", "key-b" => "value-b"} myHash["key-c"] = "value-c"
  • 25. // Create a new array: NSArray *myArray = [NSArray arrayWithObjects:@"hello",@"world",@"etc",nil]; // Create a mutable array: NSMutableArray *myArray = [[NSMutableArray alloc] init]; [myArray addObject:@"hello world"]; // Create a dictionary (hash): NSDictionary *myDictionary = [NSDictionary dictionaryWithObjectsAndKeys: @"value-a", @"key-a", @"value-b", @"key-b", nil]; // Create a mutable dictionary: NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary]; [myDictionary setObject: @"value-c" forKey: @"key-c"];
  • 26. now = -> {   puts "The date and time is: #{Time.now}" } now.call
  • 27. void (^now)(void) = ^ {   NSDate *date = [NSDate date];   NSLog(@"The date and time is %@", date); }; now();
  • 29. require 'net/http' require 'json' url = "http://www.example.com/api.json" response = Net::HTTP.get_response(URI.parse(url)) if response.code.to_i == 200   json = JSON.parse(response.body)   puts json.inspect else   puts "An Error Occurred (#{response.code}): #{response.body}" end
  • 30. - (void)viewDidLoad {   [super viewDidLoad];   responseData = [[NSMutableData data] retain];   NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com/api.json"]];   [[NSURLConnection alloc] initWithRequest:request delegate:self]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {   [responseData setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {   [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {   label.text = [NSString stringWithFormat:@"Connection failed: %@", [error description]]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection {   [connection release];   NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];   [responseData release];      NSError *error;   SBJSON *json = [[SBJSON new] autorelease];   NSArray *myArray = [json objectWithString:responseString error:&error];   [responseString release];      if (myArray == nil)     label.text = [NSString stringWithFormat:@"JSON parsing failed: %@", [error localizedDescription]];   else {     NSMutableString *text = [NSMutableString stringWithString:@"Array Data:n"];          for (int i = 0; i < [myArray count]; i++)       [text appendFormat:@"%@n", [myArray objectAtIndex:i]];     label.text = text;   } }
  • 31.
  • 32.
  • 33. Laurent Sansonetti ✦ Worked for Apple for 7 years on iLife and OS X ✦ Developed MacRuby ✦ Developed RubyCocoa ✦ Belgian
  • 34. So What Does it Do?
  • 35. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!)
  • 36. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Keep Your Editor (NO XCODE!)
  • 37. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Keep Your Editor (NO XCODE!) ✦ IRB
  • 38. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Keep Your Editor (NO XCODE!) ✦ IRB ✦ Terminal Based Workflow (Rake)
  • 39. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Keep Your Editor (NO XCODE!) ✦ IRB ✦ Terminal Based Workflow (Rake) ✦ Testing Framework (MacBacon)
  • 40. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Native Applications ✦ Keep Your Editor (NO XCODE!) ✦ IRB ✦ Terminal Based Workflow (Rake) ✦ Testing Framework (MacBacon)
  • 41. So What Does it Do? ✦ Ruby!!! (NO OBJECTIVE-C!) ✦ Native Applications ✦ Keep Your Editor (NO XCODE!) ✦ App Store Approved ✦ IRB ✦ Terminal Based Workflow (Rake) ✦ Testing Framework (MacBacon)
  • 43. NSString *urlAsString = @"http://www.apple.com"; NSURL *url = [NSURL URLWithString:urlAsString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection  sendAsynchronousRequest:urlRequest  queue:queue  completionHandler:^(NSURLResponse *response,                      NSData *data,                      NSError *error) {        if ([data length] >0 &&        error == nil){            /* Get the documents directory */      NSString *documentsDir =      [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,                                           NSUserDomainMask,                                           YES) objectAtIndex:0];            /* Append the file name to the documents directory */      NSString *filePath = [documentsDir                            stringByAppendingPathComponent:@"apple.html"];            /* Write the data to the file */      [data writeToFile:filePath             atomically:YES];            NSLog(@"Successfully saved the file to %@", filePath);          }    else if ([data length] == 0 &&             error == nil){      NSLog(@"Nothing was downloaded.");    }    else if (error != nil){      NSLog(@"Error happened = %@", error);    }      }];
  • 44. url = NSURL.URLWithString("http://www.apple.com") request = NSURLRequest.requestWithURL(url) queue = NSOperationQueue.alloc.init NSURLConnection.sendAsynchronousRequest(request,   queue: queue,   completionHandler: lambda do |response, data, error|     if(data.length > 0 && error.nil?)       doc_dir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,                                                     NSUserDomainMask,                                                     true).first       #p doc_dir       file_path = doc_dir.stringByAppendingPathComponent("apple.html")       data.writeToFile(file_path, atomically: true)       p "Saved file to #{file_path}"     elsif( data.length == 0 && error.nil? )       p "Nothing was downloaded"     elsif(!error.nil?)       p "Error: #{error}"     end   end)
  • 45. But What About Those Weird Named Argument Methods?
  • 46. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {   // do something } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {   // do something } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {   // do something }
  • 47. def tableView(tableView, didSelectRowAtIndexPath: indexPath)   # do something end def tableView(tableView, numberOfRowsInSection: section)   # do something end def tableView(tableView, cellForRowAtIndexPath: indexPath)   # do something end
  • 50. HTTP data = {first_name: 'Matt', last_name: 'Aimonetti'} BubbleWrap::HTTP.post("http://foo.bar.com/", {payload: data}) do |response| if response.ok? json = BubbleWrap::JSON.parse(response.body.to_str) p json['id'] elsif response.status_code.to_s =~ /40d/ App.alert("Login failed") else App.alert(response.error_message) end end
  • 51. App > App.documents_path # "~/iPhone Simulator/5.0/Applications/EEC6454E-1816-451E-BB9A-EE18222E1A8F/Documents" > App.resources_path # "~/iPhone Simulator/5.0/Applications/EEC64-1816-451E-BB9A-EE18221A8F/testSuite_spec.app" > App.name # "testSuite" > App.identifier # "io.bubblewrap.testSuite" > App.alert("BubbleWrap is awesome!") # creates and shows an alert message. > App.run_after(0.5) { p "It's #{Time.now}" } # Runs the block after 0.5 seconds. > App.open_url("http://matt.aimonetti.net") # Opens the url using the device's browser. (accepts a string url or an instance of NSURL. > App::Persistence['channels'] # application specific persistence storage # ['NBC', 'ABC', 'Fox', 'CBS', 'PBS'] > App::Persistence['channels'] = ['TF1', 'France 2', 'France 3'] # ['TF1', 'France 2', 'France 3']
  • 52. Device > Device.iphone? # true > Device.ipad? # false > Device.front_camera? # true > Device.rear_camera? # true > Device.orientation # :portrait > Device.simulator? # true > Device.retina? # false > Device.screen.width # 320 > Device.screen.height # 480 > Device.screen.width_for_orientation(:landscape_left) # 480 > Device.screen.height_for_orientation(:landscape_left) # 320
  • 53. Camera # Uses the front camera BW::Device.camera.front.picture(media_types: [:movie, :image]) do |result| image_view = UIImageView.alloc.initWithImage(result[:original_image]) end # Uses the rear camera BW::Device.camera.rear.picture(media_types: [:movie, :image]) do |result| image_view = UIImageView.alloc.initWithImage(result[:original_image]) end # Uses the photo library BW::Device.camera.any.picture(media_types: [:movie, :image]) do |result| image_view = UIImageView.alloc.initWithImage(result[:original_image]) end
  • 54. JSON BW::JSON.generate({'foo => 1, 'bar' => [1,2,3], 'baz => 'awesome'}) => "{"foo":1,"bar":[1,2,3],"baz":"awesome"}" BW::JSON.parse "{"foo":1,"bar":[1,2,3],"baz":"awesome"}" => {"foo"=>1, "bar"=>[1, 2, 3], "baz"=>"awesome"}
  • 55. Media # Plays in your custom frame local_file = NSURL.fileURLWithPath(File.join(NSBundle.mainBundle.resourcePath, 'test.mp3')) BW::Media.play(local_file) do |media_player| media_player.view.frame = [[10, 100], [100, 100]] self.view.addSubview media_player.view end # Plays in an independent modal controller BW::Media.play_modal("http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3")
  • 56. Deferrables > d = EM::DefaultDeferrable.new => #<BubbleWrap::Reactor::DefaultDeferrable:0x6d859a0> > d.callback { |what| puts "Great #{what}!" } => [#<Proc:0x6d8a1e0>] > d.succeed "justice" Great justice! => nil
  • 57. Events > o = Class.new { include EM::Eventable }.new => #<#<Class:0x6dc1310>:0x6dc2ec0> > o.on(:november_5_1955) { puts "Ow!" } => [#<Proc:0x6dc6300>] > o.on(:november_5_1955) { puts "Flux capacitor!" } => [#<Proc:0x6dc6300>, #<Proc:0x6dc1ba0>] > o.trigger(:november_5_1955) Ow! Flux capacitor! => [nil, nil]
  • 58. More... ✦ Localization ✦ Location ✦ Color ✦ Gestures ✦ UUID Generator ✦ RSS Parser ✦ NSNotificationCenter ✦ Reactor ✦ Persistence ✦ Timers ✦ Observers ✦ String (underscore, camelize, etc...)
  • 61. The Pros ✦ Ruby!!
  • 62. The Pros ✦ Ruby!! ✦ IDE Agnostic
  • 63. The Pros ✦ Ruby!! ✦ IDE Agnostic ✦ “Wrapper” Gems
  • 64. The Pros ✦ Ruby!! ✦ IDE Agnostic ✦ “Wrapper” Gems ✦ Fast
  • 65. The Pros ✦ Ruby!! ✦ IDE Agnostic ✦ “Wrapper” Gems ✦ Fast ✦ IRB
  • 66. The Pros ✦ Ruby!! ✦ Easy to test ✦ IDE Agnostic ✦ “Wrapper” Gems ✦ Fast ✦ IRB
  • 67. The Pros ✦ Ruby!! ✦ Easy to test ✦ IDE Agnostic ✦ Growing community ✦ “Wrapper” Gems ✦ Fast ✦ IRB
  • 68. The Pros ✦ Ruby!! ✦ Easy to test ✦ IDE Agnostic ✦ Growing community ✦ “Wrapper” Gems ✦ Frequent updates ✦ Fast ✦ IRB
  • 70. The Cons ✦ Cost - $199
  • 71. The Cons ✦ Cost - $199 ✦ Existing tutorials in Objective-C
  • 72. The Cons ✦ Cost - $199 ✦ Existing tutorials in Objective-C ✦ Maintainability?
  • 73. The Cons ✦ Cost - $199 ✦ Existing tutorials in Objective-C ✦ Maintainability? ✦ No Debugger (Yet)
  • 74. The Cons ✦ Cost - $199 ✦ Existing tutorials in Objective-C ✦ Maintainability? ✦ No Debugger (Yet) ✦ Difficult to work with Interface Builder
  • 76. Resources ✦ http://www.rubymotion.com ✦ http://rubymotionapps.com/projects ✦ http://rubymotion-tutorial.com ✦ http://pragmaticstudio.com/screencasts/ rubymotion ✦ https://github.com/IconoclastLabs/ rubymotion_cookbook ✦ https://github.com/railsfactory/ rubymotion-cookbook ✦ https://twitter.com/RubyMotion ✦ http://rubymotionweekly.com

Hinweis der Redaktion

  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
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n