-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lnstagram\@justtrotana #4270
base: master
Are you sure you want to change the base?
lnstagram\@justtrotana #4270
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_xaii77
and wrappers used to wrap Cocoa Touch and AppKit code and provide more Ruby like APIs. Installationgem install bubble-wrap Setup
require 'bubble-wrap' If you use Bundler: gem 'bubble-wrap', '~> 1.9.7' BubbleWrap is split into multiple modules so that you can easily choose which parts are included at compile-time. If you wish to only include the require 'bubble-wrap/rss_parser' If you wish to only include the require 'bubble-wrap/reactor' If you wish to only include the UI-related wrappers: require 'bubble-wrap/ui' If you wish to only include the require 'bubble-wrap/camera' If you wish to only include the require 'bubble-wrap/location' If you wish to only include the require 'bubble-wrap/media' If you wish to only include the require 'bubble-wrap/mail' If you wish to only include the require 'bubble-wrap/sms' If you wish to only include the require 'bubble-wrap/motion' If you wish to only include the require 'bubble-wrap/network-indicator' If you want to include everything (ie kitchen sink mode) you can save time and do: require 'bubble-wrap/all' You can also do this directly in your gem 'bubble-wrap', require: %w[bubble-wrap/core bubble-wrap/location, bubble-wrap/reactor] Note: DON'T use
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
puts "#{App.name} (#{App.documents_path})"
true
end
end Note: You can also vendor this repository but the recommended way is to CoreMiscUUID generator: BubbleWrap.create_uuid
=> "68ED21DB-82E5-4A56-ABEB-73650C0DB701" Localization (using BubbleWrap.localized_string(:foo, 'fallback')
=> "fallback" Color conversion: BubbleWrap.rgba_color(23, 45, 12, 0.4)
=> #<UIDeviceRGBColor:0x6db6ed0>
BubbleWrap.rgb_color(23, 45, 12)
=> #<UIDeviceRGBColor:0x8ca88b0>
'blue'.to_color
=> #<UICachedDeviceRGBColor:0xda535c0>
'dark_gray'.to_color
=> #<UICachedDeviceWhiteColor:0x8bb5be0>
'#FF8A19'.to_color
=> #<UIDeviceRGBColor:0x8d54110>
'#88FF8A19'.to_color # ARGB format
=> #<UIDeviceRGBColor:0xca0fe00> Debug flag: BubbleWrap.debug?
=> false
BubbleWrap.debug = true
=> true
BubbleWrap.debug?
=> true AppA module with useful methods related to the running application > App.documents_path
# "/Users/mattetti/Library/Application Support/iPhone Simulator/5.0/Applications/EEC6454E-1816-451E-BB9A-EE18222E1A8F/Documents"
> App.resources_path
# "/Users/mattetti/Library/Application Support/iPhone Simulator/5.0/Applications/EEC6454E-1816-451E-BB9A-EE18222E1A8F/testSuite_spec.app"
> App.name
# "testSuite"
> App.identifier
# "io.bubblewrap.testSuite"
> App.alert("BubbleWrap is awesome!")
# creates and shows an alert message.
> App.alert("BubbleWrap is awesome!", {cancel_button_title: "I know it is!", message: "Like, seriously awesome."})
# creates and shows an alert message with optional parameters.
> App.run_after(0.5) { p "It's #{Time.now}" }
# Runs the block after 0.5 seconds.
> App.open_url("http://matt.aimonetti.net")
> App.open_url("tel://123456789")
# Opens the url using the device's browser. Can also open custom URL schemas (accepts a string url or an instance of `NSURL`.)
> App.can_open_url("tel://")
# Returns whether the app can open a given URL resource.
> 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']
> App.environment
# 'test' Other available methods:
DeviceA collection of useful methods about the current device: Examples: > Device.iphone?
# true
> Device.ipad?
# false
> Device.camera.front?
# true
> Device.camera.rear?
# true
> Device.orientation
# :portrait
> Device.interface_orientation
# :portrait
> Device.simulator?
# true
> Device.ios_version
# "6.0"
> 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
> Device.vendor_identifier
# <NSUUID> CameraAdded interface for better camera access: # 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
# Lets the user edit the photo (with access to the edited and original photos)
BW::Device.camera.any.picture(allows_editing: true, media_types: [:image]) do |result|
edited_image_view = UIImageView.alloc.initWithImage(result[:edited_image])
original_image_view = UIImageView.alloc.initWithImage(result[:original_image])
end
# Capture a low quality movie with a limit of 10 seconds
BW::Device.camera.front.picture(media_types: [:movie], video_quality: :low, video_maximum_duration: 10) do |result|
video_file_path = result[:media_url]
end Options include:
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"} NSIndexPathHelper methods added to give index_path = table_view.indexPathForCell(cell)
index_path + 1 # NSIndexPath for next cell in the same section
=> #<NSIndexPath:0x120db8e0> NSNotificationCenterHelper methods to give NSNotificationCenter a Ruby-like interface: def viewWillAppear(animated)
@foreground_observer = App.notification_center.observe UIApplicationWillEnterForegroundNotification do |notification|
loadAndRefresh
end
@reload_observer = App.notification_center.observe 'ReloadNotification' do |notification|
loadAndRefresh
end
end
def viewWillDisappear(animated)
App.notification_center.unobserve @foreground_observer
App.notification_center.unobserve @reload_observer
end
def reload
App.notification_center.post 'ReloadNotification'
end NSUserDefaultsHelper methods added to the class repsonsible for user preferences used PersistenceOffers a way to persist application specific information using a very > 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']
> App::Persistence.delete('channels')
# ['TF1', 'France 2', 'France 3']
> App::Persistence['something__new'] # something previously never stored
# nil
> App::Persistence.all
# {'all':'values', 'stored':'by', 'bubblewrap':'as a hash!'} ObserversSince: > version 0.4 You can observe for object's changes and trigger blocks: class ExampleViewController < UIViewController
include BW::KVO
def viewDidLoad
@label = UILabel.alloc.initWithFrame [[20,20],[280,44]]
@label.text = ""
view.addSubview @label
observe(@label, :text) do |old_value, new_value|
puts "Hello from viewDidLoad!"
end
end
def viewDidAppear(animated)
observe(@label, :text) do |old_value, new_value|
puts "Hello from viewDidAppear!"
end
end
end You can remove observers using Since: > version 1.9.0 Optionally, multiple key paths can be passed to the class ExampleViewController < UIViewController
include BW::KVO
def viewDidLoad
@label = UILabel.alloc.initWithFrame [[20,20],[280,44]]
@label.text = ""
view.addSubview @label
observe(@label, [:text, :textColor]) do |old_value, new_value, key_path|
puts "Hello from viewDidLoad for #{key_path}!"
end
end
end Also you can use StringThe Ruby > "matt_aimonetti".camelize
=> "MattAimonetti"
> "MattAimonetti".underscore
=> "matt_aimonetti" TimeThe > Time.iso8601("2012-05-31T19:41:33Z")
=> 2012-05-31 21:41:33 +0200 LocationInterface for Ruby-like GPS and compass access (the CoreLocation framework): > BW::Location.enabled? # Whether location services are enabled on the device
=> true
> BW::Location.authorized? # If your app is authorized to use location services
=> false BW::Location.get(purpose: 'We need to use your GPS because...') do |result|
p "From Lat #{result[:from].latitude}, Long #{result[:from].longitude}"
p "To Lat #{result[:to].latitude}, Long #{result[:to].longitude}"
end Note: The BW::Location.get_compass do |result|
p result[:magnetic_heading] # Heading towards magnetic north
p result[:true_heading] # Heading towards true north
p result[:accuracy] # Potential error between magnetic and true heading
p result[:timestamp] # Timestamp of the heading calculation
end
BW::Location.get_once(desired_accuracy: :three_kilometers, ...) do |result|
if result.is_a?(CLLocation)
p result.coordinate.latitude
p result.coordinate.longitude
else
p "ERROR: #{result[:error]}"
end
end
BW::Location.get_compass_once do |heading|
p result[:magnetic_heading]
p result[:true_heading]
p result[:accuracy]
p result[:timestamp]
end iOS 8 Location RequirementsiOS 8 introduced stricter location services requirements. Although BubbleWrap will handle most of this for you automatically, you are required to add a few key/value pairs to the app.info_plist['NSLocationAlwaysUsageDescription'] = 'Description'
app.info_plist['NSLocationWhenInUseUsageDescription'] = 'Description' Note: you need both keys to use MotionInterface for the accelerometer, gyroscope, and magnetometer sensors (the Each sensor has an The
If you pass a string instead, a new queue will be created and its The AccelerometerBW::Motion.accelerometer.available?
BW::Motion.accelerometer.data # returns CMAccelerometerData object or nil
# ask the CMMotionManager to update every 5 seconds
BW::Motion.accelerometer.every(5) do |result|
# result contains the following data (from CMAccelerometerData#acceleration):
p result[:data] # the CMAccelerometerData object
p result[:acceleration] # the CMAcceleration struct
p result[:x] # acceleration in the x direction
p result[:y] # " y direction
p result[:z] # " z direction
end
# every, start, and repeat all need to be stopped later.
BW::Motion.accelerometer.stop
# repeat, but don't set the interval
BW::Motion.accelerometer.repeat do |result|
end
# you can specify a :queue where the operations will be executed. See above for details
BW::Motion.accelerometer.every(5, queue: :background) { |result| ... }
BW::Motion.accelerometer.every(5, queue: :main) { |result| ... }
BW::Motion.accelerometer.every(5, queue: :current) { |result| ... }
BW::Motion.accelerometer.every(5, queue: 'my queue') { |result| ... }
BW::Motion.accelerometer.once do |result|
# ...
end GyroscopeBW::Motion.gyroscope.available?
BW::Motion.gyroscope.data # returns CMGyroData object or nil
# ask the CMMotionManager to update every second.
BW::Motion.gyroscope.every(1) do |result|
# result contains the following data (from CMGyroData#rotationRate):
p result[:data] # the CMGyroData object
p result[:rotation] # the CMRotationRate struct
p result[:x] # rotation in the x direction
p result[:y] # " y direction
p result[:z] # " z direction
end
BW::Motion.gyroscope.stop
BW::Motion.gyroscope.once do |result|
# ...
end MagnetometerBW::Motion.magnetometer.available?
BW::Motion.magnetometer.data # returns CMMagnetometerData object or nil
# ask the CMMotionManager to update every second
BW::Motion.magnetometer.every(1) do |result|
# result contains the following data (from CMMagnetometerData#magneticField):
p result[:data] # the CMMagnetometerData object
p result[:field] # the CMMagneticField struct
p result[:x] # magnetic field in the x direction
p result[:y] # " y direction
p result[:z] # " z direction
end
BW::Motion.magnetometer.stop
BW::Motion.magnetometer.once do |result|
# ...
end Device MotionThis is an amalgam of all the motion sensor data. BW::Motion.device.available?
BW::Motion.device.data # returns CMDeviceMotion object or nil
BW::Motion.device.every(1) do |result|
# result contains the following data:
p result[:data] # the CMDeviceMotion object
# orientation data, from CMDeviceMotion#attitude
p result[:attitude] # the CMAttitude struct
p result[:roll]
p result[:pitch]
p result[:yaw]
# rotation data, from CMDeviceMotion#rotationRate
p result[:rotation] # the CMRotationRate struct
p result[:rotation_x]
p result[:rotation_y]
p result[:rotation_z]
# gravity+acceleration vector, from CMDeviceMotion#gravity
p result[:gravity] # the CMAcceleration struct
p result[:gravity_x]
p result[:gravity_y]
p result[:gravity_z]
# just the acceleration vector, from CMDeviceMotion#userAcceleration
p result[:acceleration] # the CMAcceleration struct
p result[:acceleration_x]
p result[:acceleration_y]
p result[:acceleration_z]
# the magnetic data, from CMDeviceMotion#magneticField
p result[:magnetic] # the CMCalibratedMagneticField struct
p result[:magnetic_field] # the CMMagneticField struct from the CMCalibratedMagneticField
p result[:magnetic_x]
p result[:magnetic_y]
p result[:magnetic_z]
p result[:magnetic_accuracy] # this will be a symbol, :low, :medium, :high, or nil if the magnetic data is uncalibrated
# less useful data from CMAttitude, unless you're into the whole linear algebra thing:
p result[:matrix] # CMAttitude#rotationMatrix
p result[:quarternion] # CMAttitude#quarternion
end
# the reference frame should be one of the CMAttitudeReferenceFrame constants...
ref = CMAttitudeReferenceFrameXArbitraryZVertical
# ... or one of these symbols: :arbitrary_z, :corrected_z, :magnetic_north, :true_north
ref = :corrected_z
BW::Motion.device.every(1, queue: :background, reference: ref) { |result| ... }
BW::Motion.device.once do |result|
# ...
end MediaAdded wrapper for playing remote and local media. Available are # 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") Wrapper for showing an in-app mail composer view. You should always determine if the device your app is running on is configured to send mail before displaying a mail composer window. # Opens as a modal in the current UIViewController
BW::Mail.compose(
delegate: self, # optional, defaults to rootViewController
to: [ "[email protected]" ],
cc: [ "[email protected]", "[email protected]" ],
bcc: [ "[email protected]" ],
html: false,
subject: "My Subject",
message: "This is my message. It isn't very long.",
animated: false
) do |result, error|
result.sent? # => boolean
result.canceled? # => boolean
result.saved? # => boolean
result.failed? # => boolean
error # => NSError
end SMSWrapper for showing an in-app message (SMS) composer view. You should always determine if the device your app is running on can send SMS messages before displaying a SMS composer window. # Opens as a modal in the current UIViewController
BW::SMS.compose (
{
delegate: self, # optional, will use root view controller by default
to: [ "1(234)567-8910" ],
message: "This is my message. It isn't very long.",
animated: false
}) {|result, error|
result.sent? # => boolean
result.canceled? # => boolean
result.failed? # => boolean
error # => NSError
} NetworkIndicatorWrapper for showing and hiding the network indicator (the status bar spinner). BW::NetworkIndicator.show # starts the spinner
BW::NetworkIndicator.hide # stops it
# the nice thing is if you call 'show' multiple times, the 'hide' method will
# not have any effect until you've called it the same number of times.
BW::NetworkIndicator.show
# ...somewhere else
BW::NetworkIndicator.show
# ...down the line
BW::NetworkIndicator.hide
# indicator is still visible
BW::NetworkIndicator.hide
# NOW the indicator is hidden!
# If you *really* want to hide the indicator immediately, you can call `reset!`
# but this is in no way encouraged.
BW::NetworkIndicator.reset!
# and for completeness, a check to see if the indicator is visible
BW::NetworkIndicator.visible? UIGesturesExtra methods on view.when_tapped do
UIView.animateWithDuration(1,
animations:lambda {
# animate
# @view.transform = ...
})
end There are similar methods for In order to prevent retain cycles due to strong references within the passed block, use the use_weak_callbacks flag so the blocks do not retain a strong reference to self: BubbleWrap.use_weak_callbacks = true UIViewControllerA custom method was added to UIControl / UIButtonHelper methods to give button.when(UIControlEventTouchUpInside) do
self.view.backgroundColor = UIColor.redColor
end The button.when(UIControlEventTouchUpInside | UIControlEventTouchUpOutside) do
self.view.backgroundColor = UIColor.redColor
end You can use symbols for events (but won't work with the bitwise operator): button.when(:touch_up_inside) do
self.view.backgroundColor = UIColor.redColor
end
button.when(:value_changed) do
self.view.backgroundColor = UIColor.blueColor
end Set the use_weak_callbacks flag so the blocks do not retain a strong reference to self: BubbleWrap.use_weak_callbacks = true UIBarButtonItem
ConstructorsInstead specifying a target-action pair, each constructor method accepts an optional block. When the button is tapped, the block is executed. BW::UIBarButtonItem.system(:save) do
# ...
end
title = "Friends"
BW::UIBarButtonItem.styled(:plain, title) do
# ...
end
image = UIImage.alloc.init
BW::UIBarButtonItem.styled(:bordered, image) do
# ...
end
image = UIImage.alloc.init
landscape = UIImage.alloc.init
BW::UIBarButtonItem.styled(:bordered, image, landscape) do
# ...
end
view = UIView.alloc.init
BW::UIBarButtonItem.custom(view) do
# ...
end
# NOTE: The block is attached to the view as a single tap gesture recognizer. The options = { :system => :save }
BW::UIBarButtonItem.new(options) do
# ...
end
options = { :styled => :plain, :title => "Friends" }
BW::UIBarButtonItem.new(options) do
# ...
end
options = { :styled => :bordered, :image => UIImage.alloc.init }
BW::UIBarButtonItem.new(options) do
# ...
end
options = {
:styled => :bordered,
:image => UIImage.alloc.init,
:landscape => UIImage.alloc.init
}
BW::UIBarButtonItem.new(options) do
# ...
end
options = { :custom => UIView.alloc.init }
BW::UIBarButtonItem.new(options) do
# ...
end
# NOTE: The block is attached to the view as a single tap gesture recognizer. Button typesThe :plain
:bordered
:done And the :done
:cancel
:edit
:save
:add
:flexible_space
:fixed_space
:compose
:reply
:action
:organize
:bookmarks
:search
:refresh
:stop
:camera
:trash
:play
:pause
:rewind
:fast_forward
:undo
:redo
:page_curl UIActivityViewController
You can initiate a # Without a completion handler
BW::UIActivityViewController.new(
items: "Some Text", # or ["Some Text", NSURL.URLWithString('http://www.rubymotion.com')] or a UIImage
animated: true, # Defaults to true
excluded: :add_to_reading_list # One item or an array
)
# With completion handler
BW::UIActivityViewController.new(
items: "Some Text",
animated: true,
excluded: [:add_to_reading_list, :print, :air_drop]
) do |activity_type, completed|
puts "completed with activity: #{activity_type} - finished?: #{completed}"
end Built in activities that can be passed to the :post_to_facebook
:post_to_twitter
:post_to_weibo
:message
:mail
:print
:copy_to_pasteboard
:assign_to_contact
:save_to_camera_roll
:add_to_reading_list
:post_to_flickr
:post_to_vimeo
:post_to_tencent_weibo
:air_drop RSS ParserSince: > version 1.0.0 The RSS Parser provides an easy interface to consume RSS feeds in an feed_parser = BW::RSSParser.new("http://feeds2.feedburner.com/sdrbpodcast")
feed_parser.parse do |item|
# called asynchronously as items get parsed
p item.title
end The yielded RSS item is of type
The item can be converted into a hash by calling DelegateSince: > version 1.0.0 You can also designate a delegate to the parser and implement change feed_parser = BW::RSSParser.new("http://feeds.feedburner.com/sdrbpodcast")
feed_parser.delegate = self
feed_parser.parse do |item|
p item.title
end
# Delegate method
def when_parser_initializes
p "The parser is ready!"
end
def when_parser_parses
p "The parser started parsing the document"
end
def when_parser_is_done
p "The feed is entirely parsed, congratulations!"
end
def when_parser_errors
p "The parser encountered an error"
ns_error = feed_parser.parserError
p ns_error.localizedDescription
end These delegate methods are optional, however, you might find the Parsing a remote content or actual dataYou have the choice to initialize a parser instance with a string # string representing an url:
feed_parser = BW::RSSParser.new("http://feeds2.feedburner.com/sdrbpodcast")
# a NSURL instance:
url = NSURL.alloc.initWithString("http://matt.aimonetti.net/atom.xml")
feed_parser = BW::RSSParser.new(url)
# Some data
feed = File.read('atom.xml')
feed_parser = BW::RSSParser.new(feed, true) ReactorSince: > version 1.0.0
DeferablesBubbleWrap provides both a A deferrable is an object with four states: unknown, successful, failure Using By default, callbacks will be made on the thread that the deferrable Success> d = EM::DefaultDeferrable.new
=> #<BW::Reactor::DefaultDeferrable:0x6d859a0>
> d.callback { |what| puts "Great #{what}!" }
=> [#<Proc:0x6d8a1e0>]
> d.succeed "justice"
Great justice!
=> nil Failure> d = EM::DefaultDeferrable.new
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
> d.errback { |what| puts "Great #{what}!" }
=> [#<Proc:0x8bf3ef0>]
> d.fail "sadness"
Great sadness!
=> nil Delegate> d = EM::DefaultDeferrable.new
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
> delegate = EM::DefaultDeferrable.new
=> #<BW::Reactor::DefaultDeferrable:0x8bf5910>
> d.delegate delegate
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
> delegate.callback { |*args| puts args }
=> [#<Proc:0x8bf3ef0>]
> d.succeed :passed
=> nil
=> [:passed] DependentDeferrable
> d1 = EM::DefaultDeferrable.new
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x10c713750>
> d2 = EM::DefaultDeferrable.new
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x10370bb10>
> d = EM::DependentDeferrable.on(d1, d2)
=> #<BubbleWrap::Reactor::DependentDeferrable:0x106c17b80>
> d.callback {|a, b| puts "a: #{a} b: #{b}"}
=> [#<Proc:0x103075210>]
> d1.succeed 'one', 'one more'
> d2.succeed :two
a: ["one", "one more"] b: [:two] ThreadAwareDeferrable> d = EM::ThreadAwareDeferrable.new
=> #<BW::Reactor::ThreadAwareDeferrable:0x8bf3ee0>
> queue = Dispatch::Queue.new(:deferrable.to_s)
> queue.async do
> d.callback do |*args|
> Dispatch::Queue.current == queue
> => true # this is normally false
> end
> end
> d.succeed true Timeout> d = EM::DefaultDeferrable.new
=> #<BW::Reactor::DefaultDeferrable:0x8bf5910>
> d.errback { puts "Great scott!" }
=> [#<Proc:0x8bf6350>]
> d.timeout 2
=> #<BW::Reactor::Timer:0x6d920a0 @timer=#<__NSCFTimer:0x6d91990>>
# wait...
> Great scott! TimersAll timers can be cancelled using One-shot timers> EM.add_timer 1.0 do
> puts "Great scott!"
> end
=> 146335904
> Great scott! Periodic timers> count = 0
=> 0
> timer = EM.add_periodic_timer 1.0 do
> count = count + 1
> puts "Great scott!"
> (count < 10) || EM.cancel_timer(timer)
> end
=> 146046832
> Great scott!
Great scott!
Great scott!
Great scott!
Great scott!
Great scott!
Great scott!
Great scott!
Great scott!
Great scott! Scheduling operationsYou can use > EM.schedule { puts Thread.current.object_id }
146027920
=> nil
> EM.schedule_on_main { puts Thread.current.object_id }
112222480
=> nil Deferrable operationsYou can also use > operation = proc { 88 }
=> #<Proc:0x6d763c0>
> callback = proc { |speed| puts speed >= 88 ? "Time travel!" : "Conventional travel!" }
=> #<Proc:0x8bd3910>
> EM.defer(operation, callback)
=> nil
Time travel! EventsAlthough not part of the EventMachine API, BubbleWrap provides > o = Class.new { include EM::Eventable }.new
=> #<#<Class:0xab63f00>:0xab64430>
> o.on(:november_5_1955) { puts "Ow!" }
=> [#<Proc:0xad9bf00>]
> flux = proc{ puts "Flux capacitor!" }
=> #<Proc:0xab630f0>
> o.on(:november_5_1955, &flux)
=> [#<Proc:0xad9bf00>, #<Proc:0xab630f0>]
> o.trigger(:november_5_1955)
Ow!
Flux capacitor!
=> [nil, nil]
> o.off(:november_5_1955, &flux)
=> #<Proc:0xab630f0>
> o.trigger(:november_5_1955)
Ow!
=> [nil]
> o.on(:november_5_1955) { puts "Ow!" }
> o.on(:november_5_1955) { puts "Another Ow!" }
> o.off(:november_5_1955)
=> nil ContributingDo you have a suggestion for a specific wrapper? Feel free to open an
|
R