bubble-wrap 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +1 -1
- data/GETTING_STARTED.md +1 -1
- data/Gemfile.lock +10 -10
- data/README.md +266 -122
- data/Rakefile +1 -1
- data/bubble-wrap.gemspec +7 -6
- data/lib/bubble-wrap.rb +0 -1
- data/lib/bubble-wrap/all.rb +13 -1
- data/lib/bubble-wrap/location.rb +1 -1
- data/lib/bubble-wrap/motion.rb +10 -0
- data/lib/bubble-wrap/rss_parser.rb +0 -1
- data/lib/bubble-wrap/test.rb +1 -0
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core/device/ios/camera.rb +12 -1
- data/motion/core/ios/device.rb +7 -1
- data/motion/core/json.rb +1 -1
- data/motion/core/osx/app.rb +11 -1
- data/motion/core/time.rb +27 -4
- data/motion/location/location.rb +6 -2
- data/motion/mail/mail.rb +4 -0
- data/motion/media/player.rb +2 -1
- data/motion/motion/motion.rb +421 -0
- data/motion/reactor/deferrable.rb +29 -3
- data/motion/reactor/eventable.rb +3 -1
- data/motion/reactor/thread_aware_deferrable.rb +37 -0
- data/motion/rss_parser.rb +11 -21
- data/motion/sms/sms.rb +4 -0
- data/motion/ui/ui_alert_view.rb +3 -1
- data/motion/ui/ui_control_wrapper.rb +27 -0
- data/motion/ui/ui_view_wrapper.rb +1 -7
- data/motion/util/constants.rb +1 -1
- data/samples/alert/Gemfile +1 -0
- data/samples/alert/Gemfile.lock +16 -0
- data/samples/alert/Rakefile +1 -1
- data/samples/camera/Gemfile +2 -1
- data/samples/camera/Gemfile.lock +16 -0
- data/samples/camera/Rakefile +1 -1
- data/samples/gesture/Gemfile +2 -1
- data/samples/gesture/Gemfile.lock +9 -3
- data/samples/gesture/Rakefile +1 -1
- data/samples/location/Gemfile +3 -1
- data/samples/location/Gemfile.lock +18 -0
- data/samples/location/Rakefile +4 -2
- data/samples/location/app/controllers/{image_list_controller.rb → places_list_controller.rb} +0 -0
- data/samples/media/Gemfile +4 -0
- data/samples/media/Gemfile.lock +16 -0
- data/samples/media/Rakefile +1 -1
- data/samples/osx/Gemfile +3 -1
- data/samples/osx/Gemfile.lock +5 -1
- data/spec/lib/bubble-wrap/requirement_spec.rb +2 -2
- data/spec/motion/core/app_spec.rb +23 -0
- data/spec/motion/core/device/ios/camera_spec.rb +1 -1
- data/spec/motion/core/device/ios/device_spec.rb +6 -0
- data/spec/motion/core/ios/app_spec.rb +9 -24
- data/spec/motion/core/json_spec.rb +30 -10
- data/spec/motion/core/osx/app_spec.rb +2 -1
- data/spec/motion/core/time_spec.rb +34 -1
- data/spec/motion/location/location_spec.rb +6 -0
- data/spec/motion/mail/mail_spec.rb +20 -16
- data/spec/motion/motion/core_motion_spec.rb +231 -0
- data/spec/motion/reactor/deferrable_spec.rb +81 -0
- data/spec/motion/reactor/eventable_spec.rb +11 -0
- data/spec/motion/reactor/thread_aware_deferrable_spec.rb +85 -0
- data/spec/motion/rss_parser_spec.rb +11 -21
- data/spec/motion/sms/sms_spec.rb +11 -6
- data/spec/motion/ui/ui_alert_view_spec.rb +23 -0
- data/spec/motion/ui/ui_control_wrapper_spec.rb +24 -0
- metadata +58 -38
- data/lib/bubble-wrap/http.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf1fb0a71b37c7e7473219036a4d8304dd7c9fd1
|
4
|
+
data.tar.gz: 1f57a00000623dac2a425cceb6ce5f74ae40eb3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e259382ebbc9970d3b264f9a95961807944bb17da2aec89f6af873d4b267e1319d2ac1dfc86cd0a2ef08d205cf9719160a10d7db5bf32c51c8926fdc2f332ec2
|
7
|
+
data.tar.gz: edced4a22d3af5a7f067a08a84176206aa039632adf97b46411582a33f0cd8a6b256f730aecbf73c3a639a51d404d563d163d76973680fecb38b73d661d28c01
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/GETTING_STARTED.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bubble-wrap (1.
|
5
|
-
bubble-wrap-http (= 1.7.1)
|
4
|
+
bubble-wrap (1.8.0)
|
6
5
|
|
7
6
|
GEM
|
8
7
|
remote: https://rubygems.org/
|
9
8
|
specs:
|
10
|
-
bacon (1.
|
11
|
-
|
12
|
-
metaclass (0.0.1)
|
9
|
+
bacon (1.2.0)
|
10
|
+
metaclass (0.0.4)
|
13
11
|
mocha (0.11.4)
|
14
12
|
metaclass (~> 0.0.1)
|
15
13
|
mocha-on-bacon (0.2.1)
|
16
14
|
mocha (>= 0.9.8)
|
17
|
-
rake (
|
15
|
+
rake (10.3.2)
|
16
|
+
webstub (1.1.2)
|
18
17
|
|
19
18
|
PLATFORMS
|
20
19
|
ruby
|
21
20
|
|
22
21
|
DEPENDENCIES
|
23
|
-
bacon
|
22
|
+
bacon (~> 1.2)
|
24
23
|
bubble-wrap!
|
25
|
-
mocha (
|
26
|
-
mocha-on-bacon
|
27
|
-
rake
|
24
|
+
mocha (~> 0.11)
|
25
|
+
mocha-on-bacon (~> 0.2)
|
26
|
+
rake (~> 10.0)
|
27
|
+
webstub (~> 1.1)
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ A collection of (tested) helpers and wrappers used to wrap Cocoa Touch and AppKi
|
|
5
5
|
[BubbleWrap website](http://rubymotion.github.io/BubbleWrap/)
|
6
6
|
[BubbleWrap mailing list](https://groups.google.com/forum/#!forum/bubblewrap)
|
7
7
|
|
8
|
-
[![Code Climate](https://codeclimate.com/github/rubymotion/BubbleWrap.
|
8
|
+
[![Code Climate](https://codeclimate.com/github/rubymotion/BubbleWrap.svg)](https://codeclimate.com/github/rubymotion/BubbleWrap)
|
9
9
|
[![Build Status](https://travis-ci.org/rubymotion/BubbleWrap.svg?branch=master)](https://travis-ci.org/rubymotion/BubbleWrap)
|
10
10
|
[![Dependency Status](https://gemnasium.com/rubymotion/BubbleWrap.png)](https://gemnasium.com/rubymotion/BubbleWrap)
|
11
11
|
|
@@ -26,24 +26,10 @@ require 'bubble-wrap'
|
|
26
26
|
If you using Bundler:
|
27
27
|
|
28
28
|
```ruby
|
29
|
-
gem "bubble-wrap", "~> 1.
|
29
|
+
gem "bubble-wrap", "~> 1.8.0"
|
30
30
|
```
|
31
31
|
|
32
|
-
BubbleWrap is split into multiple modules so that you can easily choose which parts
|
33
|
-
are included at compile-time.
|
34
|
-
|
35
|
-
The above example requires the `core` and `http` modules. If you wish to only
|
36
|
-
include the core modules use the following line of code instead:
|
37
|
-
|
38
|
-
```ruby
|
39
|
-
require 'bubble-wrap/core'
|
40
|
-
```
|
41
|
-
|
42
|
-
If you wish to only include the `HTTP` wrapper:
|
43
|
-
|
44
|
-
```ruby
|
45
|
-
require 'bubble-wrap/http'
|
46
|
-
```
|
32
|
+
BubbleWrap is split into multiple modules so that you can easily choose which parts are included at compile-time.
|
47
33
|
|
48
34
|
If you wish to only include the `RSS Parser` wrapper:
|
49
35
|
|
@@ -105,6 +91,11 @@ If you want to include everything (ie kitchen sink mode) you can save time and d
|
|
105
91
|
require 'bubble-wrap/all'
|
106
92
|
```
|
107
93
|
|
94
|
+
You can also do this directly in your `Gemfile` like so:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
gem 'bubble-wrap', require: %w[bubble-wrap/core bubble-wrap/location, bubble-wrap/reactor]
|
98
|
+
```
|
108
99
|
|
109
100
|
Note: **DON'T** use `app.files =` in your Rakefile to set up your files once you've required BubbleWrap.
|
110
101
|
Make sure to append onto the array or use `+=`.
|
@@ -246,6 +237,8 @@ Examples:
|
|
246
237
|
# 480
|
247
238
|
> Device.screen.height_for_orientation(:landscape_left)
|
248
239
|
# 320
|
240
|
+
> Device.vendor_identifier
|
241
|
+
# <NSUUID>
|
249
242
|
```
|
250
243
|
|
251
244
|
### Camera
|
@@ -273,8 +266,12 @@ BW::Device.camera.any.picture(allows_editing: true, media_types: [:image]) do |r
|
|
273
266
|
edited_image_view = UIImageView.alloc.initWithImage(result[:edited_image])
|
274
267
|
original_image_view = UIImageView.alloc.initWithImage(result[:original_image])
|
275
268
|
end
|
276
|
-
```
|
277
269
|
|
270
|
+
# Capture a low quality movie with a limit of 10 seconds
|
271
|
+
BW::Device.camera.front.picture(media_types: [:movie], video_quality: :low, video_maximum_duration: 10) do |result|
|
272
|
+
video_file_path = result[:media_url]
|
273
|
+
end
|
274
|
+
```
|
278
275
|
|
279
276
|
Options include:
|
280
277
|
|
@@ -282,13 +279,15 @@ Options include:
|
|
282
279
|
- `:animated` - Boolean; whether to display the camera with an animation (default true)
|
283
280
|
- `:on_dismiss` - Lambda; called instead of the default dismissal logic
|
284
281
|
- `:media_types` - Array; containing any of `[:movie, :image]`
|
282
|
+
- `:video_quality` - Symbol; one of `:high`, `:medium`, `low`, `"640x480".to_sym`, `iframe1280x720`, or `iframe960x540`. Defaults to `:medium`
|
283
|
+
- `:video_maximum_duration` - Integer; limits movie recording length. Defaults to 600.
|
285
284
|
|
286
285
|
### JSON
|
287
286
|
|
288
287
|
`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](https://github.com/mattt/AnyJSON).
|
289
288
|
|
290
289
|
```ruby
|
291
|
-
BW::JSON.generate({'foo => 1, 'bar' => [1,2,3], 'baz => 'awesome'})
|
290
|
+
BW::JSON.generate({'foo' => 1, 'bar' => [1,2,3], 'baz' => 'awesome'})
|
292
291
|
=> "{\"foo\":1,\"bar\":[1,2,3],\"baz\":\"awesome\"}"
|
293
292
|
BW::JSON.parse "{\"foo\":1,\"bar\":[1,2,3],\"baz\":\"awesome\"}"
|
294
293
|
=> {"foo"=>1, "bar"=>[1, 2, 3], "baz"=>"awesome"}
|
@@ -359,9 +358,9 @@ class ExampleViewController < UIViewController
|
|
359
358
|
include BW::KVO
|
360
359
|
|
361
360
|
def viewDidLoad
|
362
|
-
|
363
|
-
|
364
|
-
|
361
|
+
@label = UILabel.alloc.initWithFrame [[20,20],[280,44]]
|
362
|
+
@label.text = ""
|
363
|
+
view.addSubview @label
|
365
364
|
|
366
365
|
observe(@label, :text) do |old_value, new_value|
|
367
366
|
puts "Hello from viewDidLoad!"
|
@@ -402,7 +401,7 @@ iso8601 formatted string into a Time instance.
|
|
402
401
|
|
403
402
|
## Location
|
404
403
|
|
405
|
-
|
404
|
+
Interface for Ruby-like GPS and compass access (the CoreLocation framework):
|
406
405
|
|
407
406
|
```ruby
|
408
407
|
> BW::Location.enabled? # Whether location services are enabled on the device
|
@@ -449,6 +448,177 @@ BW::Location.get_compass_once do |heading|
|
|
449
448
|
end
|
450
449
|
```
|
451
450
|
|
451
|
+
### iOS 8 Location Requirements
|
452
|
+
|
453
|
+
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):
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
app.info_plist['NSLocationAlwaysUsageDescription'] = 'Description'
|
457
|
+
app.info_plist['NSLocationWhenInUseUsageDescription'] = 'Description'
|
458
|
+
```
|
459
|
+
|
460
|
+
*Note: you need both keys to use `get_once`, so it's probably best to just include both no matter what.* See [Apple's documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW18) on iOS 8 location services requirements for more information.
|
461
|
+
|
462
|
+
## Motion
|
463
|
+
|
464
|
+
Interface for the accelerometer, gyroscope, and magnetometer sensors (the
|
465
|
+
CoreMotion framework). You can access each sensor individually, or you can get
|
466
|
+
data from all of them at once using the `BW::Motion.device` interface, which
|
467
|
+
delegates to `CMMotionManager#deviceMotion`.
|
468
|
+
|
469
|
+
Each sensor has an `every` and `once` method. `every` expects a time interval,
|
470
|
+
and you will need to retain the object it returns and call `#stop` on it when
|
471
|
+
you are done with the data.
|
472
|
+
|
473
|
+
The `every` and `once` methods can accept a `:queue` option. The default value
|
474
|
+
is a queue that runs on the main loop, so that UI updates can be processed in
|
475
|
+
the block. This is useful, but not recommended by Apple, since the events can
|
476
|
+
come in at a high rate. If you want to use a background queue, you can either
|
477
|
+
specify an NSOperationQueue object, or you can use one of these symbols:
|
478
|
+
|
479
|
+
- `:main` - `NSOperationQueue.mainQueue`, this is the default value.
|
480
|
+
- `:background` - BubbleWrap will create a new `NSOperationQueue`.
|
481
|
+
- `:current` - BubbleWrap will use `NSOperationQueue.currentQueue`.
|
482
|
+
|
483
|
+
If you pass a string instead, a new queue will be created and its `name`
|
484
|
+
property will be set to that string.
|
485
|
+
|
486
|
+
The `CMDeviceMotion` interface (`BW::Motion.device`) accepts a `:reference`
|
487
|
+
option, which specifies the `CMAttitudeReferenceFrame`. The default value is
|
488
|
+
the same as the one that `CMMotionManager` uses, which is returned by the
|
489
|
+
`CMMotionManager#attitudeReferenceFrame` method. This option should be passed
|
490
|
+
to the `repeat`, `every` or `once` methods.
|
491
|
+
|
492
|
+
###### Accelerometer
|
493
|
+
```ruby
|
494
|
+
BW::Motion.accelerometer.available?
|
495
|
+
BW::Motion.accelerometer.data # returns CMAccelerometerData object or nil
|
496
|
+
|
497
|
+
# ask the CMMotionManager to update every 5 seconds
|
498
|
+
BW::Motion.accelerometer.every(5) do |result|
|
499
|
+
# result contains the following data (from CMAccelerometerData#acceleration):
|
500
|
+
p result[:data] # the CMAccelerometerData object
|
501
|
+
p result[:acceleration] # the CMAcceleration struct
|
502
|
+
p result[:x] # acceleration in the x direction
|
503
|
+
p result[:y] # " y direction
|
504
|
+
p result[:z] # " z direction
|
505
|
+
end
|
506
|
+
|
507
|
+
# every, start, and repeat all need to be stopped later.
|
508
|
+
BW::Motion.accelerometer.stop
|
509
|
+
|
510
|
+
# repeat, but don't set the interval
|
511
|
+
BW::Motion.accelerometer.repeat do |result|
|
512
|
+
end
|
513
|
+
|
514
|
+
# you can specify a :queue where the operations will be executed. See above for details
|
515
|
+
BW::Motion.accelerometer.every(5, queue: :background) { |result| ... }
|
516
|
+
BW::Motion.accelerometer.every(5, queue: :main) { |result| ... }
|
517
|
+
BW::Motion.accelerometer.every(5, queue: :current) { |result| ... }
|
518
|
+
BW::Motion.accelerometer.every(5, queue: 'my queue') { |result| ... }
|
519
|
+
|
520
|
+
BW::Motion.accelerometer.once do |result|
|
521
|
+
# ...
|
522
|
+
end
|
523
|
+
```
|
524
|
+
|
525
|
+
###### Gyroscope
|
526
|
+
```ruby
|
527
|
+
BW::Motion.gyroscope.available?
|
528
|
+
BW::Motion.gyroscope.data # returns CMGyroData object or nil
|
529
|
+
|
530
|
+
# ask the CMMotionManager to update every second.
|
531
|
+
BW::Motion.gyroscope.every(1) do |result|
|
532
|
+
# result contains the following data (from CMGyroData#rotationRate):
|
533
|
+
p result[:data] # the CMGyroData object
|
534
|
+
p result[:rotation] # the CMRotationRate struct
|
535
|
+
p result[:x] # rotation in the x direction
|
536
|
+
p result[:y] # " y direction
|
537
|
+
p result[:z] # " z direction
|
538
|
+
end
|
539
|
+
BW::Motion.gyroscope.stop
|
540
|
+
|
541
|
+
BW::Motion.gyroscope.once do |result|
|
542
|
+
# ...
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
###### Magnetometer
|
547
|
+
```ruby
|
548
|
+
BW::Motion.magnetometer.available?
|
549
|
+
BW::Motion.magnetometer.data # returns CMMagnetometerData object or nil
|
550
|
+
|
551
|
+
# ask the CMMotionManager to update every second
|
552
|
+
BW::Motion.magnetometer.every(1) do |result|
|
553
|
+
# result contains the following data (from CMMagnetometerData#magneticField):
|
554
|
+
p result[:data] # the CMMagnetometerData object
|
555
|
+
p result[:field] # the CMMagneticField struct
|
556
|
+
p result[:x] # magnetic field in the x direction
|
557
|
+
p result[:y] # " y direction
|
558
|
+
p result[:z] # " z direction
|
559
|
+
end
|
560
|
+
BW::Motion.magnetometer.stop
|
561
|
+
|
562
|
+
BW::Motion.magnetometer.once do |result|
|
563
|
+
# ...
|
564
|
+
end
|
565
|
+
```
|
566
|
+
|
567
|
+
###### Device Motion
|
568
|
+
|
569
|
+
This is an amalgam of all the motion sensor data.
|
570
|
+
|
571
|
+
```ruby
|
572
|
+
BW::Motion.device.available?
|
573
|
+
BW::Motion.device.data # returns CMDeviceMotion object or nil
|
574
|
+
|
575
|
+
BW::Motion.device.every(1) do |result|
|
576
|
+
# result contains the following data:
|
577
|
+
p result[:data] # the CMDeviceMotion object
|
578
|
+
# orientation data, from CMDeviceMotion#attitude
|
579
|
+
p result[:attitude] # the CMAttitude struct
|
580
|
+
p result[:roll]
|
581
|
+
p result[:pitch]
|
582
|
+
p result[:yaw]
|
583
|
+
# rotation data, from CMDeviceMotion#rotationRate
|
584
|
+
p result[:rotation] # the CMRotationRate struct
|
585
|
+
p result[:rotation_x]
|
586
|
+
p result[:rotation_y]
|
587
|
+
p result[:rotation_z]
|
588
|
+
# gravity+acceleration vector, from CMDeviceMotion#gravity
|
589
|
+
p result[:gravity] # the CMAcceleration struct
|
590
|
+
p result[:gravity_x]
|
591
|
+
p result[:gravity_y]
|
592
|
+
p result[:gravity_z]
|
593
|
+
# just the acceleration vector, from CMDeviceMotion#userAcceleration
|
594
|
+
p result[:acceleration] # the CMAcceleration struct
|
595
|
+
p result[:acceleration_x]
|
596
|
+
p result[:acceleration_y]
|
597
|
+
p result[:acceleration_z]
|
598
|
+
# the magnetic data, from CMDeviceMotion#magneticField
|
599
|
+
p result[:magnetic] # the CMCalibratedMagneticField struct
|
600
|
+
p result[:magnetic_field] # the CMMagneticField struct from the CMCalibratedMagneticField
|
601
|
+
p result[:magnetic_x]
|
602
|
+
p result[:magnetic_y]
|
603
|
+
p result[:magnetic_z]
|
604
|
+
p result[:magnetic_accuracy] # this will be a symbol, :low, :medium, :high, or nil if the magnetic data is uncalibrated
|
605
|
+
|
606
|
+
# less useful data from CMAttitude, unless you're into the whole linear algebra thing:
|
607
|
+
p result[:matrix] # CMAttitude#rotationMatrix
|
608
|
+
p result[:quarternion] # CMAttitude#quarternion
|
609
|
+
end
|
610
|
+
|
611
|
+
# the reference frame should be one of the CMAttitudeReferenceFrame constants...
|
612
|
+
ref = CMAttitudeReferenceFrameXArbitraryZVertical
|
613
|
+
# ... or one of these symbols: :arbitrary_z, :corrected_z, :magnetic_north, :true_north
|
614
|
+
ref = :corrected_z
|
615
|
+
BW::Motion.device.every(1, queue: :background, reference: ref) { |result| ... }
|
616
|
+
|
617
|
+
BW::Motion.device.once do |result|
|
618
|
+
# ...
|
619
|
+
end
|
620
|
+
```
|
621
|
+
|
452
622
|
## Media
|
453
623
|
|
454
624
|
Added wrapper for playing remote and local media. Available are `modal` and custom presentation styles:
|
@@ -469,6 +639,8 @@ BW::Media.play_modal("http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_s
|
|
469
639
|
|
470
640
|
Wrapper for showing an in-app mail composer view.
|
471
641
|
|
642
|
+
You should always determine if the device your app is running on is configured to send mail before displaying a mail composer window. `BW::Mail.can_send_mail?` will return `true` or `false`.
|
643
|
+
|
472
644
|
```ruby
|
473
645
|
# Opens as a modal in the current UIViewController
|
474
646
|
BW::Mail.compose(
|
@@ -493,6 +665,8 @@ end
|
|
493
665
|
|
494
666
|
Wrapper for showing an in-app message (SMS) composer view.
|
495
667
|
|
668
|
+
You should always determine if the device your app is running on can send SMS messages before displaying a SMS composer window. `BW::SMS.can_send_sms?` will return `true` or `false`.
|
669
|
+
|
496
670
|
```ruby
|
497
671
|
# Opens as a modal in the current UIViewController
|
498
672
|
BW::SMS.compose (
|
@@ -556,6 +730,12 @@ Extra methods on `UIView` for working with gesture recognizers. A gesture recogn
|
|
556
730
|
|
557
731
|
There are similar methods for `pinched`, `rotated`, `swiped`, `panned`, and `pressed` (for long presses). All of the methods return the actual recognizer object, so it is possible to set the delegate if more fine-grained control is needed.
|
558
732
|
|
733
|
+
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:
|
734
|
+
|
735
|
+
```ruby
|
736
|
+
BubbleWrap.use_weak_callbacks = true
|
737
|
+
```
|
738
|
+
|
559
739
|
### UIViewController
|
560
740
|
|
561
741
|
A custom method was added to `UIViewController` to return the content
|
@@ -571,6 +751,26 @@ button.when(UIControlEventTouchUpInside) do
|
|
571
751
|
end
|
572
752
|
```
|
573
753
|
|
754
|
+
The `#when` method also accepts bitwise combinations of events:
|
755
|
+
|
756
|
+
```ruby
|
757
|
+
button.when(UIControlEventTouchUpInside | UIControlEventTouchUpOutside) do
|
758
|
+
self.view.backgroundColor = UIColor.redColor
|
759
|
+
end
|
760
|
+
```
|
761
|
+
|
762
|
+
You can use symbols for events (but won't work with the bitwise operator):
|
763
|
+
|
764
|
+
```ruby
|
765
|
+
button.when(:touch_up_inside) do
|
766
|
+
self.view.backgroundColor = UIColor.redColor
|
767
|
+
end
|
768
|
+
|
769
|
+
button.when(:value_changed) do
|
770
|
+
self.view.backgroundColor = UIColor.blueColor
|
771
|
+
end
|
772
|
+
```
|
773
|
+
|
574
774
|
Set the use_weak_callbacks flag so the blocks do not retain a strong reference to self:
|
575
775
|
|
576
776
|
```ruby
|
@@ -729,105 +929,6 @@ Built in activities that can be passed to the `excluded` option are defined as `
|
|
729
929
|
:air_drop
|
730
930
|
```
|
731
931
|
|
732
|
-
|
733
|
-
## HTTP
|
734
|
-
|
735
|
-
`BW::HTTP` wraps `NSURLRequest`, `NSURLConnection` and friends to provide Ruby developers with a more familiar and easier to use API.
|
736
|
-
The API uses async calls and blocks to stay as simple as possible.
|
737
|
-
|
738
|
-
To enable it add the following require line to your `Rakefile`:
|
739
|
-
```ruby
|
740
|
-
require 'bubble-wrap/http'
|
741
|
-
```
|
742
|
-
|
743
|
-
Usage example:
|
744
|
-
|
745
|
-
```ruby
|
746
|
-
BW::HTTP.get("https://api.github.com/users/mattetti") do |response|
|
747
|
-
p response.body.to_str
|
748
|
-
end
|
749
|
-
```
|
750
|
-
|
751
|
-
```ruby
|
752
|
-
BW::HTTP.get("https://api.github.com/users/mattetti", {credentials: {username: 'matt', password: 'aimonetti'}}) do |response|
|
753
|
-
p response.body.to_str # prints the response's body
|
754
|
-
end
|
755
|
-
```
|
756
|
-
|
757
|
-
```ruby
|
758
|
-
data = {first_name: 'Matt', last_name: 'Aimonetti'}
|
759
|
-
BW::HTTP.post("http://foo.bar.com/", {payload: data}) do |response|
|
760
|
-
if response.ok?
|
761
|
-
json = BW::JSON.parse(response.body.to_str)
|
762
|
-
p json['id']
|
763
|
-
elsif response.status_code.to_s =~ /40\d/
|
764
|
-
App.alert("Login failed")
|
765
|
-
else
|
766
|
-
App.alert(response.error_message)
|
767
|
-
end
|
768
|
-
end
|
769
|
-
```
|
770
|
-
|
771
|
-
To upload files to a server, provide a `files:` hash:
|
772
|
-
|
773
|
-
```ruby
|
774
|
-
data = {token: "some-api-token"}
|
775
|
-
avatar_data = UIImagePNGRepresentation(UIImage.imageNamed("some-image"))
|
776
|
-
avatar = { data: avatar_data, filename: "some-image.png", content_type: "image/png" }
|
777
|
-
|
778
|
-
BW::HTTP.post("http://foo.bar.com/", {payload: data}, files: { avatar: avatar }) do |response|
|
779
|
-
if response.ok?
|
780
|
-
# files are uploaded
|
781
|
-
end
|
782
|
-
end
|
783
|
-
```
|
784
|
-
|
785
|
-
A `:download_progress` option can also be passed. The expected object
|
786
|
-
would be a Proc that takes two arguments: a float representing the
|
787
|
-
amount of data currently received and another float representing the
|
788
|
-
total amount of data expected.
|
789
|
-
|
790
|
-
Connections can also be cancelled. Just keep a refrence,
|
791
|
-
|
792
|
-
```ruby
|
793
|
-
@conn = BW::HTTP.get("https://api.github.com/users/mattetti") do |response|
|
794
|
-
p response.body.to_str
|
795
|
-
end
|
796
|
-
```
|
797
|
-
|
798
|
-
and send the `cancel` method to it asynchronously as desired. The block will not be executed.
|
799
|
-
|
800
|
-
```ruby
|
801
|
-
@conn.cancel
|
802
|
-
```
|
803
|
-
|
804
|
-
### Gotchas
|
805
|
-
|
806
|
-
Because of how RubyMotion currently works, you sometimes need to assign objects as `@instance_variables` in order to retain their callbacks.
|
807
|
-
|
808
|
-
For example:
|
809
|
-
|
810
|
-
```ruby
|
811
|
-
class HttpClient
|
812
|
-
def get_user(user_id, &callback)
|
813
|
-
BW::HTTP.get(user_url(user_id)) do |response|
|
814
|
-
# ..
|
815
|
-
end
|
816
|
-
end
|
817
|
-
end
|
818
|
-
```
|
819
|
-
|
820
|
-
This class should be invoked in your code as:
|
821
|
-
|
822
|
-
```ruby
|
823
|
-
@http_client = HttpClient.new
|
824
|
-
@http_client.get_user(user_id) do |user|
|
825
|
-
# ..
|
826
|
-
end
|
827
|
-
```
|
828
|
-
|
829
|
-
(instead of doing an instance-variable-less `HttpClient.new.get_user`)
|
830
|
-
|
831
932
|
## RSS Parser
|
832
933
|
**Since: > version 1.0.0**
|
833
934
|
|
@@ -928,6 +1029,14 @@ and timeout. When you initially create a deferrable it is in an unknown
|
|
928
1029
|
state, however you can assign callbacks to be run when the object
|
929
1030
|
changes to either successful or failure state.
|
930
1031
|
|
1032
|
+
Using `delegate`, `errback_delegate` and `callback_delegate` you can link
|
1033
|
+
deferrables together.
|
1034
|
+
|
1035
|
+
By default, callbacks will be made on the thread that the deferrable
|
1036
|
+
succeeds/fails on. For multithreaded environments, it can be useful to use
|
1037
|
+
EM::ThreadAwareDeferrable so that callbacks will be made on the threads they
|
1038
|
+
are declared on.
|
1039
|
+
|
931
1040
|
#### Success
|
932
1041
|
|
933
1042
|
```ruby
|
@@ -951,6 +1060,37 @@ Great justice!
|
|
951
1060
|
Great sadness!
|
952
1061
|
=> nil
|
953
1062
|
```
|
1063
|
+
#### Delegate
|
1064
|
+
|
1065
|
+
```ruby
|
1066
|
+
> d = EM::DefaultDeferrable.new
|
1067
|
+
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
|
1068
|
+
> delegate = EM::DefaultDeferrable.new
|
1069
|
+
=> #<BW::Reactor::DefaultDeferrable:0x8bf5910>
|
1070
|
+
> d.delegate delegate
|
1071
|
+
=> #<BW::Reactor::DefaultDeferrable:0x8bf3ee0>
|
1072
|
+
> delegate.callback { |*args| puts args }
|
1073
|
+
=> [#<Proc:0x8bf3ef0>]
|
1074
|
+
> d.succeed :passed
|
1075
|
+
=> nil
|
1076
|
+
=> [:passed]
|
1077
|
+
```
|
1078
|
+
|
1079
|
+
#### ThreadAwareDeferrable
|
1080
|
+
|
1081
|
+
```ruby
|
1082
|
+
> d = EM::ThreadAwareDeferrable.new
|
1083
|
+
=> #<BW::Reactor::ThreadAwareDeferrable:0x8bf3ee0>
|
1084
|
+
|
1085
|
+
> queue = Dispatch::Queue.new(:deferrable.to_s)
|
1086
|
+
> queue.async do
|
1087
|
+
> d.callback do |*args|
|
1088
|
+
> Dispatch::Queue.current == queue
|
1089
|
+
> => true # this is normally false
|
1090
|
+
> end
|
1091
|
+
> end
|
1092
|
+
> d.succeed true
|
1093
|
+
```
|
954
1094
|
|
955
1095
|
#### Timeout
|
956
1096
|
|
@@ -1064,6 +1204,10 @@ Flux capacitor!
|
|
1064
1204
|
> o.trigger(:november_5_1955)
|
1065
1205
|
Ow!
|
1066
1206
|
=> [nil]
|
1207
|
+
> o.on(:november_5_1955) { puts "Ow!" }
|
1208
|
+
> o.on(:november_5_1955) { puts "Another Ow!" }
|
1209
|
+
> o.off(:november_5_1955)
|
1210
|
+
=> nil
|
1067
1211
|
```
|
1068
1212
|
|
1069
1213
|
# Suggestions?
|