bubble-wrap 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](https://codeclimate.com/github/rubymotion/BubbleWrap)
|
9
9
|
[](https://travis-ci.org/rubymotion/BubbleWrap)
|
10
10
|
[](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?
|