Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
B

BubbleWrap

> 编程语言
Open source

Cocoa wrappers and helpers for RubyMotion (Ruby for iOS and OS X) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull requests

1.2K stars0 likes2 views
WebsiteGitHub

About

Cocoa wrappers and helpers for RubyMotion (Ruby for iOS and OS X) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull requests

BubbleWrap for RubyMotion

A collection of (tested) helpers and wrappers used to wrap Cocoa Touch and AppKit code and provide more Ruby like APIs.

Installation

ruby
gem install bubble-wrap

Setup

  1. Edit the Rakefile of your RubyMotion project and add the following require line:
ruby
require 'bubble-wrap'

If you use Bundler:

ruby
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 RSS Parser wrapper:

ruby
require 'bubble-wrap/rss_parser'

If you wish to only include the Reactor wrapper:

ruby
require 'bubble-wrap/reactor'

If you wish to only include the UI-related wrappers:

ruby
require 'bubble-wrap/ui'

If you wish to only include the Camera wrapper:

ruby
require 'bubble-wrap/camera'

If you wish to only include the Location wrapper:

ruby
require 'bubble-wrap/location'

If you wish to only include the Media wrapper:

ruby
require 'bubble-wrap/media'

If you wish to only include the Mail wrapper:

ruby
require 'bubble-wrap/mail'

If you wish to only include the SMS wrapper:

ruby
require 'bubble-wrap/sms'

If you wish to only include the Motion (CoreMotion) wrapper:

ruby
require 'bubble-wrap/motion'

If you wish to only include the NetworkIndicator wrapper:

ruby
require 'bubble-wrap/network-indicator'

If you want to include everything (ie kitchen sink mode) you can save time and do:

ruby
require 'bubble-wrap/all'

You can also do this directly in your Gemfile like so:

ruby
gem 'bubble-wrap', require: %w[bubble-wrap/core bubble-wrap/location, bubble-wrap/reactor]

Note: DON'T use app.files = in your Rakefile to set up your files once you've required BubbleWrap. Make sure to append onto the array or use +=.

  1. Now, you can use BubbleWrap extension in your app:
ruby
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 use the versioned gem.

Core

Misc

UUID generator:

ruby
BubbleWrap.create_uuid
=> "68ED21DB-82E5-4A56-ABEB-73650C0DB701"

Localization (using NSBundle.mainBundle.localizedStringForKey):

ruby
BubbleWrap.localized_string(:foo, 'fallback')
=> "fallback"

Color conversion:

ruby
BubbleWrap.rgba_color(23, 45, 12, 0.4)
=> #
BubbleWrap.rgb_color(23, 45, 12)
=> #
'blue'.to_color
=> #
'dark_gray'.to_color
=> #
'#FF8A19'.to_color
=> #
'#88FF8A19'.to_color # ARGB format
=> #

Debug flag:

ruby
BubbleWrap.debug?
=> false
BubbleWrap.debug = true
=> true
BubbleWrap.debug?
=> true

App

A module with useful methods related to the running application

…

Other available methods:

  • App.notification_center
  • App.user_cache
  • App.states
  • App.frame
  • App.delegate
  • App.shared
  • App.window
  • App.current_locale
  • App.release?
  • App.test?
  • App.development?

Device

A collection of useful methods about the current device:

Examples:

ruby
> 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
# 

Camera

Added interface for better camera access:

…

Options include:

  • :allows_editing - Boolean; whether a user can edit the photo/video before picking
  • :animated - Boolean; whether to display the camera with an animation (default true)
  • :on_dismiss - Lambda; called instead of the default dismissal logic
  • :media_types - Array; containing any of [:movie, :image]
  • :video_quality - Symbol; one of :high, :medium, low, "640x480".to_sym, iframe1280x720, or iframe960x540. Defaults to :medium
  • :video_maximum_duration - Integer; limits movie recording length. Defaults to 600.

JSON

BW::JSON wraps NSJSONSerialization available in iOS5 and offers the same API as Ruby's JSON std lib. For apps building for iOS4, we suggest a different JSON alternative, like AnyJSON.

ruby
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"}

NSIndexPath

Helper methods added to give NSIndexPath a bit more of a Ruby interface.

ruby
index_path = table_view.indexPathForCell(cell)
index_path + 1 # NSIndexPath for next cell in the same section
=> #

NSNotificationCenter

Helper methods to give NSNotificationCenter a Ruby-like interface:

ruby
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

NSUserDefaults

Helper methods added to the class repsonsible for user preferences used by the App::Persistence module shown below.

Persistence

Offers a way to persist application specific information using a very simple interface:

ruby
> 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!'}

Observers

Since: > version 0.4

You can observe for object's changes and trigger blocks:

ruby
class ExampleViewController  version 1.9.0**

Optionally, multiple key paths can be passed to the `observer` method:

``` ruby
class ExampleViewController  "matt_aimonetti".camelize
=> "MattAimonetti"
> "MattAimonetti".underscore
=> "matt_aimonetti"

Time

The Time Ruby class was added a class level method to convert a iso8601 formatted string into a Time instance.

ruby
> Time.iso8601("2012-05-31T19:41:33Z")
=> 2012-05-31 21:41:33 +0200

Location

Interface for Ruby-like GPS and compass access (the CoreLocation framework):

ruby
> 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
ruby
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

…

ruby
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_significant is also available, for monitoring significant location changes.

BW::Location also supports get_once-style methods, which will return the first result before ending the search:

ruby
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 Requirements

iOS 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 Info.plist. Add these two lines to your Rakefile (with your descriptions, obviously):

ruby
app.info_plist['NSLocationAlwaysUsageDescription'] = 'Description'
app.info_plist['NSLocationWhenInUseUsageDescription'] = 'Description'

…

ruby
BW::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
Gyroscope
ruby
BW::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
Magnetometer
ruby
BW::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 Motion

This is an amalgam of all the motion sensor data.

ruby
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[:gravi

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Ruby

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言