bubble-wrap 1.8.0 → 1.9.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/.travis.yml +14 -9
- data/CHANGELOG.md +21 -2
- data/Gemfile.lock +8 -5
- data/README.md +54 -3
- data/Rakefile +7 -1
- data/lib/bubble-wrap/camera.rb +1 -1
- data/lib/bubble-wrap/core.rb +1 -1
- data/lib/bubble-wrap/font.rb +1 -1
- data/lib/bubble-wrap/loader.rb +4 -4
- data/lib/bubble-wrap/media.rb +1 -1
- data/lib/bubble-wrap/motion.rb +7 -1
- data/lib/bubble-wrap/version.rb +2 -2
- data/motion/core/app.rb +4 -0
- data/motion/core/device/ios/camera_wrapper.rb +1 -1
- data/motion/core/device/ios/screen.rb +2 -2
- data/motion/core/device/osx/screen.rb +1 -1
- data/motion/core/device/screen.rb +1 -1
- data/motion/core/ios/device.rb +1 -1
- data/motion/core/ios/ns_index_path.rb +11 -0
- data/motion/core/json.rb +2 -2
- data/motion/core/kvo.rb +118 -55
- data/motion/core/ns_notification_center.rb +2 -2
- data/motion/core/ns_url_request.rb +2 -2
- data/motion/core/osx/device.rb +1 -1
- data/motion/core/string.rb +7 -7
- data/motion/font/font.rb +1 -1
- data/motion/ios/8/location_constants.rb +21 -0
- data/motion/location/location.rb +38 -18
- data/motion/mail/result.rb +1 -1
- data/motion/media/media.rb +1 -1
- data/motion/motion/accelerometer.rb +55 -0
- data/motion/motion/device_motion.rb +139 -0
- data/motion/motion/gyroscope.rb +55 -0
- data/motion/motion/magnetometer.rb +55 -0
- data/motion/motion/motion.rb +0 -288
- data/motion/reactor.rb +3 -3
- data/motion/reactor/deferrable.rb +32 -32
- data/motion/reactor/periodic_timer.rb +1 -1
- data/motion/reactor/queue.rb +6 -6
- data/motion/reactor/thread_aware_deferrable.rb +1 -1
- data/motion/reactor/timer.rb +1 -1
- data/motion/rss_parser.rb +6 -3
- data/motion/shortcut.rb +1 -1
- data/motion/sms/result.rb +1 -1
- data/motion/test_suite_delegate.rb +1 -1
- data/motion/ui/ui_activity_view_controller_wrapper.rb +6 -1
- data/motion/ui/ui_alert_view.rb +21 -1
- data/motion/util/deprecated.rb +1 -1
- data/samples/alert/Gemfile.lock +1 -1
- data/spec/lib/bubble-wrap/requirement_spec.rb +2 -2
- data/spec/lib/bubble-wrap_spec.rb +1 -1
- data/spec/lib/motion_stub.rb +1 -1
- data/spec/motion/core/app_spec.rb +6 -0
- data/spec/motion/core/device/osx/screen_spec.rb +1 -1
- data/spec/motion/core/ios/ns_index_path_spec.rb +20 -0
- data/spec/motion/core/kvo_spec.rb +171 -58
- data/spec/motion/core/ns_notification_center_spec.rb +3 -3
- data/spec/motion/core/string_spec.rb +16 -16
- data/spec/motion/core_spec.rb +3 -3
- data/spec/motion/font/font_spec.rb +1 -1
- data/spec/motion/location/location_spec.rb +61 -9
- data/spec/motion/mail/result_spec.rb +7 -7
- data/spec/motion/media/player_spec.rb +1 -1
- data/spec/motion/reactor/thread_aware_deferrable_spec.rb +3 -3
- data/spec/motion/sms/result_spec.rb +6 -6
- data/spec/motion/ui/ui_alert_view_spec.rb +59 -1
- data/spec/motion/util/deprecated_spec.rb +1 -1
- metadata +17 -4
- data/motion/ios/7/uiactivity_view_controller_constants.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77584cd0711e17af5282a0e9f40306916177b6d5
|
4
|
+
data.tar.gz: a12694fd9f1a6e370a9d91f3ed15f3ce74af6469
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0fa5d162a946c67f83a77b56b84426f42c62770a10a027523cb2ab0e5c0958e9f657ebfb5e5fda060174aaacdc2faaf22e9f6f5b984b8db73a6bf96866495e2
|
7
|
+
data.tar.gz: 18fbc4e01a2091678107341a57d1067d2ec3341dadec26c180baf863cdfb1d034ff69046e04ecd6c5242937ae5ee410b9cf80270d55a30bd8af996be921881ea
|
data/.travis.yml
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
language: objective-c
|
2
2
|
before_install:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
- (ruby --version)
|
4
|
+
- sudo chown -R travis ~/Library/RubyMotion
|
5
|
+
- sudo mkdir -p ~/Library/RubyMotion/build
|
6
|
+
- sudo chown -R travis ~/Library/RubyMotion/build
|
7
|
+
- sudo motion update
|
8
|
+
gemfile:
|
9
|
+
- Gemfile
|
7
10
|
script:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
- bundle install --jobs=3 --retry=3
|
12
|
+
- bundle exec rake clean
|
13
|
+
- bundle exec rake spec
|
14
|
+
- bundle exec rake clean
|
15
|
+
- bundle exec rake spec target=7.1
|
16
|
+
- bundle exec rake clean
|
17
|
+
- bundle exec rake spec osx=true
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,29 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
-
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.
|
3
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.9.0...master)
|
4
|
+
|
5
|
+
## 1.9.0
|
6
|
+
|
7
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.8.0...v1.9.0)
|
8
|
+
|
9
|
+
* Add support for `keyboardType` on first input field of `BW::UIAlertView` ([#406](https://github.com/rubymotion/BubbleWrap/pull/406))
|
10
|
+
* Implement #+ and #- for NSIndexPath to incr/decr row ([#420](https://github.com/rubymotion/BubbleWrap/pull/420))
|
11
|
+
* Extract CoreMotion classes to make it easier to use and more maintainable ([#454](https://github.com/rubymotion/BubbleWrap/pull/454))
|
12
|
+
* Motion extract classes ([#454](https://github.com/rubymotion/BubbleWrap/pull/454))
|
13
|
+
* Added RSS fields: creator, category, encoded ([#461](https://github.com/rubymotion/BubbleWrap/pull/461))
|
14
|
+
* KVO `observe!` and ability to pass multiple key paths to `observe` ([#460](https://github.com/rubymotion/BubbleWrap/pull/460))
|
15
|
+
* `App.short_version` ([#466](https://github.com/rubymotion/BubbleWrap/pull/466))
|
16
|
+
* Bump the required version of iOS to >= 7 ([#424](https://github.com/rubymotion/BubbleWrap/pull/424))
|
17
|
+
* Bump the required version of iOS to >= 7 ([#424](https://github.com/rubymotion/BubbleWrap/pull/424))
|
18
|
+
* Fixes to CoreLocation ([#422](https://github.com/rubymotion/BubbleWrap/pull/422)) & ([#432](https://github.com/rubymotion/BubbleWrap/pull/432))
|
19
|
+
* Adds default text option to BW::UIAlertView ([#467](https://github.com/rubymotion/BubbleWrap/pull/467))
|
20
|
+
* Bump the minimum required RubyMotion version to `3.12`.
|
21
|
+
|
22
|
+
## ... nothing to see here... move along.
|
4
23
|
|
5
24
|
## 1.4.0
|
6
25
|
|
7
|
-
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.3.0...
|
26
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/v1.3.0...v1.4.0)
|
8
27
|
|
9
28
|
* Added `BW::Mail` for sending emails ([#247](https://github.com/rubymotion/BubbleWrap/pull/247))
|
10
29
|
* Added `BW::SMS` for sending SMS/iMessages ([#287](https://github.com/rubymotion/BubbleWrap/pull/287))
|
data/Gemfile.lock
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bubble-wrap (1.
|
4
|
+
bubble-wrap (1.9.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
bacon (1.2.0)
|
10
10
|
metaclass (0.0.4)
|
11
|
-
mocha (0.
|
11
|
+
mocha (0.14.0)
|
12
12
|
metaclass (~> 0.0.1)
|
13
|
-
mocha-on-bacon (0.2.
|
14
|
-
mocha (>= 0.
|
15
|
-
rake (10.
|
13
|
+
mocha-on-bacon (0.2.2)
|
14
|
+
mocha (>= 0.13.0)
|
15
|
+
rake (10.4.2)
|
16
16
|
webstub (1.1.2)
|
17
17
|
|
18
18
|
PLATFORMS
|
@@ -25,3 +25,6 @@ DEPENDENCIES
|
|
25
25
|
mocha-on-bacon (~> 0.2)
|
26
26
|
rake (~> 10.0)
|
27
27
|
webstub (~> 1.1)
|
28
|
+
|
29
|
+
BUNDLED WITH
|
30
|
+
1.10.4
|
data/README.md
CHANGED
@@ -7,6 +7,7 @@ A collection of (tested) helpers and wrappers used to wrap Cocoa Touch and AppKi
|
|
7
7
|
|
8
8
|
[](https://codeclimate.com/github/rubymotion/BubbleWrap)
|
9
9
|
[](https://travis-ci.org/rubymotion/BubbleWrap)
|
10
|
+
[](http://badge.fury.io/rb/bubble-wrap)
|
10
11
|
[](https://gemnasium.com/rubymotion/BubbleWrap)
|
11
12
|
|
12
13
|
## Installation
|
@@ -26,7 +27,7 @@ require 'bubble-wrap'
|
|
26
27
|
If you using Bundler:
|
27
28
|
|
28
29
|
```ruby
|
29
|
-
gem "bubble-wrap", "~> 1.
|
30
|
+
gem "bubble-wrap", "~> 1.9.0"
|
30
31
|
```
|
31
32
|
|
32
33
|
BubbleWrap is split into multiple modules so that you can easily choose which parts are included at compile-time.
|
@@ -79,6 +80,12 @@ If you wish to only include the `SMS` wrapper:
|
|
79
80
|
require 'bubble-wrap/sms'
|
80
81
|
```
|
81
82
|
|
83
|
+
If you wish to only include the `Motion` (CoreMotion) wrapper:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
require 'bubble-wrap/motion'
|
87
|
+
```
|
88
|
+
|
82
89
|
If you wish to only include the `NetworkIndicator` wrapper:
|
83
90
|
|
84
91
|
```ruby
|
@@ -298,6 +305,11 @@ BW::JSON.parse "{\"foo\":1,\"bar\":[1,2,3],\"baz\":\"awesome\"}"
|
|
298
305
|
Helper methods added to give `NSIndexPath` a bit more of a Ruby
|
299
306
|
interface.
|
300
307
|
|
308
|
+
```ruby
|
309
|
+
index_path = table_view.indexPathForCell(cell)
|
310
|
+
index_path + 1 # NSIndexPath for next cell in the same section
|
311
|
+
=> #<NSIndexPath:0x120db8e0>
|
312
|
+
```
|
301
313
|
|
302
314
|
### NSNotificationCenter
|
303
315
|
|
@@ -376,6 +388,32 @@ class ExampleViewController < UIViewController
|
|
376
388
|
end
|
377
389
|
```
|
378
390
|
|
391
|
+
You can remove observers using `unobserve` method.
|
392
|
+
|
393
|
+
**Since: > version 1.9.0**
|
394
|
+
|
395
|
+
Optionally, multiple key paths can be passed to the `observer` method:
|
396
|
+
|
397
|
+
``` ruby
|
398
|
+
class ExampleViewController < UIViewController
|
399
|
+
include BW::KVO
|
400
|
+
|
401
|
+
def viewDidLoad
|
402
|
+
@label = UILabel.alloc.initWithFrame [[20,20],[280,44]]
|
403
|
+
@label.text = ""
|
404
|
+
view.addSubview @label
|
405
|
+
|
406
|
+
observe(@label, [:text, :textColor]) do |old_value, new_value, key_path|
|
407
|
+
puts "Hello from viewDidLoad for #{key_path}!"
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
```
|
412
|
+
|
413
|
+
Also you can use `observe!` method to register observer that will immediately
|
414
|
+
return initial value. Note that in this case only new value will be passed to
|
415
|
+
the block.
|
416
|
+
|
379
417
|
|
380
418
|
### String
|
381
419
|
|
@@ -416,6 +454,10 @@ BW::Location.get(purpose: 'We need to use your GPS because...') do |result|
|
|
416
454
|
p "To Lat #{result[:to].latitude}, Long #{result[:to].longitude}"
|
417
455
|
end
|
418
456
|
```
|
457
|
+
*Note: `result[:from]` will return `nil` the first time location services are started.*
|
458
|
+
|
459
|
+
The `:previous` key in the `BW::Location.get()` result hash will always return an array of zero or more additional `CLLocation` objects aside from the locations returned from the `:to` and `:from` hash keys. While in most scenarios this array will be empty, per [Apple's Documentation](https://developer.apple.com/library/IOs/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/index.html#//apple_ref/occ/intfm/CLLocationManagerDelegate/locationManager:didUpdateLocations:) if there are deferred updates or multiple locations that arrived before they could be delivered, multiple locations will be returned in an order of oldest to newest.
|
460
|
+
|
419
461
|
|
420
462
|
```ruby
|
421
463
|
BW::Location.get_compass do |result|
|
@@ -1210,9 +1252,18 @@ Ow!
|
|
1210
1252
|
=> nil
|
1211
1253
|
```
|
1212
1254
|
|
1213
|
-
#
|
1255
|
+
# Contributing
|
1214
1256
|
|
1215
1257
|
Do you have a suggestion for a specific wrapper? Feel free to open an
|
1216
1258
|
issue/ticket and tell us about what you are after. If you have a
|
1217
1259
|
wrapper/helper you are using and are thinking that others might enjoy,
|
1218
|
-
please send a pull request
|
1260
|
+
please send a pull request with tests. If you need help writing the tests,
|
1261
|
+
send the pull request anyways and we'll try to help you out with that.
|
1262
|
+
|
1263
|
+
1. Create an issue in GitHub to make sure your PR will be accepted
|
1264
|
+
2. Fork the BubbleWrap repository
|
1265
|
+
3. Create your feature branch (`git checkout -b my-new-feature`)
|
1266
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
1267
|
+
5. Write tests for your changes and ensure they pass locally (`bundle exec rake spec && bundle exec rake spec osx=true`)
|
1268
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
1269
|
+
7. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -32,9 +32,15 @@ Motion::Project::App.setup do |app|
|
|
32
32
|
app.spec_files -= Dir.glob("./spec/motion/#{package}/**/*.rb")
|
33
33
|
end
|
34
34
|
else
|
35
|
+
app.deployment_target = '7.1'
|
36
|
+
app.info_plist['NSLocationAlwaysUsageDescription'] = 'Description'
|
37
|
+
app.info_plist['NSLocationWhenInUseUsageDescription'] = 'Description'
|
38
|
+
|
35
39
|
app.spec_files -= Dir.glob("./spec/motion/**/osx/**.rb")
|
36
40
|
end
|
37
|
-
|
41
|
+
|
42
|
+
app.version = '1.2.3'
|
43
|
+
app.short_version = '3.2.1'
|
38
44
|
end
|
39
45
|
|
40
46
|
namespace :spec do
|
data/lib/bubble-wrap/camera.rb
CHANGED
data/lib/bubble-wrap/core.rb
CHANGED
data/lib/bubble-wrap/font.rb
CHANGED
data/lib/bubble-wrap/loader.rb
CHANGED
@@ -48,13 +48,13 @@ unless defined?(BubbleWrap::LOADER_PRESENT)
|
|
48
48
|
|
49
49
|
def after_config(config)
|
50
50
|
BubbleWrap.require_ios do
|
51
|
-
|
52
|
-
if config.send(:deployment_target).to_f >=
|
53
|
-
::BubbleWrap.require(
|
51
|
+
ios8_files = 'motion/ios/8/location_constants.rb'
|
52
|
+
if config.send(:deployment_target).to_f >= 8.0
|
53
|
+
::BubbleWrap.require(ios8_files)
|
54
54
|
before_config(config)
|
55
55
|
else
|
56
56
|
config.files = config.files.reject {|s|
|
57
|
-
s.include?(
|
57
|
+
s.include?(ios8_files)
|
58
58
|
}
|
59
59
|
end
|
60
60
|
end
|
data/lib/bubble-wrap/media.rb
CHANGED
data/lib/bubble-wrap/motion.rb
CHANGED
@@ -5,6 +5,12 @@ BubbleWrap.require_ios('motion') do
|
|
5
5
|
BubbleWrap.require('motion/core/string.rb')
|
6
6
|
BubbleWrap.require('motion/motion/**/*.rb') do
|
7
7
|
file('motion/motion/motion.rb').depends_on 'motion/util/constants.rb'
|
8
|
+
|
9
|
+
file('motion/motion/accelerometer.rb').depends_on('motion/motion/motion.rb')
|
10
|
+
file('motion/motion/device_motion.rb').depends_on('motion/motion/motion.rb')
|
11
|
+
file('motion/motion/gyroscope.rb').depends_on('motion/motion/motion.rb')
|
12
|
+
file('motion/motion/magnetometer.rb').depends_on('motion/motion/motion.rb')
|
13
|
+
|
8
14
|
file('motion/motion/motion.rb').uses_framework('CoreMotion')
|
9
15
|
end
|
10
|
-
end
|
16
|
+
end
|
data/lib/bubble-wrap/version.rb
CHANGED
data/motion/core/app.rb
CHANGED
@@ -78,7 +78,7 @@ module BubbleWrap
|
|
78
78
|
# compensating for screen rotation (which
|
79
79
|
# can do your head in).
|
80
80
|
def width_for_orientation(o=orientation)
|
81
|
-
return height if (o == :landscape_left) || (o == :landscape_right)
|
81
|
+
return height if (o == :landscape_left) || (o == :landscape_right)
|
82
82
|
width
|
83
83
|
end
|
84
84
|
|
@@ -86,7 +86,7 @@ module BubbleWrap
|
|
86
86
|
# compensating for screen rotation (which
|
87
87
|
# can do your head in).
|
88
88
|
def height_for_orientation(o=orientation)
|
89
|
-
return width if (o == :landscape_left) || (o == :landscape_right)
|
89
|
+
return width if (o == :landscape_left) || (o == :landscape_right)
|
90
90
|
height
|
91
91
|
end
|
92
92
|
end
|
data/motion/core/ios/device.rb
CHANGED
@@ -13,7 +13,7 @@ module BubbleWrap
|
|
13
13
|
def ipad?(idiom=UIDevice.currentDevice.userInterfaceIdiom)
|
14
14
|
idiom == UIUserInterfaceIdiomPad
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# Verifies that the device having a long screen (4 inch iPhone/iPod)
|
18
18
|
# @return [TrueClass, FalseClass] true will be returned if the device is an iPhone/iPod with 4 inche screen, false otherwise.
|
19
19
|
def long_screen?(idiom=UIDevice.currentDevice.userInterfaceIdiom, screen_height=UIScreen.mainScreen.bounds.size.height)
|
data/motion/core/json.rb
CHANGED
data/motion/core/kvo.rb
CHANGED
@@ -18,93 +18,156 @@
|
|
18
18
|
# @see https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i
|
19
19
|
module BubbleWrap
|
20
20
|
module KVO
|
21
|
-
|
22
|
-
|
21
|
+
class Registry
|
22
|
+
COLLECTION_OPERATIONS = [ NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, NSKeyValueChangeReplacement ]
|
23
|
+
OPTION_MAP = {
|
24
|
+
new: NSKeyValueChangeNewKey,
|
25
|
+
old: NSKeyValueChangeOldKey
|
26
|
+
}
|
27
|
+
|
28
|
+
attr_reader :callbacks, :keys
|
29
|
+
|
30
|
+
def initialize(value_keys = [:old, :new])
|
31
|
+
@keys = value_keys.inject([]) do |acc, key|
|
32
|
+
value_change_key = OPTION_MAP[key]
|
33
|
+
|
34
|
+
if value_change_key.nil?
|
35
|
+
raise RuntimeError, "Unknown value change key #{key}. Possible keys: #{OPTION_MAP.keys}"
|
36
|
+
end
|
37
|
+
|
38
|
+
acc << value_change_key
|
39
|
+
end
|
23
40
|
|
24
|
-
|
25
|
-
|
26
|
-
|
41
|
+
@callbacks = Hash.new do |hash, key|
|
42
|
+
hash[key] = Hash.new do |subhash, subkey|
|
43
|
+
subhash[subkey] = Array.new
|
44
|
+
end
|
45
|
+
end
|
27
46
|
end
|
28
47
|
|
29
|
-
key_path
|
30
|
-
|
48
|
+
def add(target, key_path, &block)
|
49
|
+
return if target.nil? || key_path.nil? || block.nil?
|
31
50
|
|
32
|
-
|
33
|
-
add_observer_block(target, key_path, &block)
|
34
|
-
end
|
51
|
+
block.weak! if BubbleWrap.use_weak_callbacks?
|
35
52
|
|
36
|
-
|
37
|
-
unless [1,2].include?(arguments.length)
|
38
|
-
raise ArgumentError, "wrong number of arguments (#{arguments.length} for 1 or 2)"
|
53
|
+
callbacks[target][key_path.to_s] << block
|
39
54
|
end
|
40
55
|
|
41
|
-
|
42
|
-
|
56
|
+
def remove(target, key_path)
|
57
|
+
return if target.nil? || key_path.nil?
|
43
58
|
|
44
|
-
|
59
|
+
key_path = key_path.to_s
|
45
60
|
|
46
|
-
|
47
|
-
remove_observer_block(target, key_path)
|
48
|
-
end
|
61
|
+
callbacks[target].delete(key_path)
|
49
62
|
|
50
|
-
|
51
|
-
|
63
|
+
# If there no key_paths left for target, remove the target key
|
64
|
+
if callbacks[target].empty?
|
65
|
+
callbacks.delete(target)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def registered?(target, key_path)
|
70
|
+
callbacks[target].has_key? key_path.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
def remove_all
|
74
|
+
callbacks.clear
|
75
|
+
end
|
52
76
|
|
53
|
-
|
54
|
-
|
55
|
-
|
77
|
+
def each_key_path
|
78
|
+
callbacks.each do |target, key_paths|
|
79
|
+
key_paths.each_key do |key_path|
|
80
|
+
yield target, key_path
|
81
|
+
end
|
56
82
|
end
|
57
83
|
end
|
58
|
-
remove_all_observer_blocks
|
59
|
-
end
|
60
84
|
|
61
|
-
|
85
|
+
private
|
62
86
|
|
63
|
-
|
64
|
-
|
65
|
-
|
87
|
+
def observeValueForKeyPath(key_path, ofObject: target, change: change, context: context)
|
88
|
+
key_paths = callbacks[target] || {}
|
89
|
+
blocks = key_paths[key_path] || []
|
90
|
+
|
91
|
+
args = change.values_at(*keys)
|
92
|
+
args << key_path
|
93
|
+
|
94
|
+
blocks.each do |block|
|
95
|
+
block.call(*args)
|
96
|
+
end
|
97
|
+
end
|
66
98
|
end
|
67
99
|
|
68
|
-
|
69
|
-
|
100
|
+
DEFAULT_OPTIONS = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
|
101
|
+
IMMIDEATE_OPTIONS = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
|
70
102
|
|
71
|
-
|
103
|
+
def observe(target = self, key_paths, &block)
|
104
|
+
key_paths = [key_paths].flatten
|
72
105
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
106
|
+
key_paths.each do |key_path|
|
107
|
+
if not observers_registry.registered?(target, key_path)
|
108
|
+
target.addObserver(observers_registry, forKeyPath:key_path, options:DEFAULT_OPTIONS, context:nil)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Add block even if observer is registed, so multiplie blocks can be invoked.
|
112
|
+
observers_registry.add(target, key_path, &block)
|
113
|
+
end
|
77
114
|
end
|
78
115
|
|
79
|
-
def
|
80
|
-
|
116
|
+
def observe!(target = self, key_paths, &block)
|
117
|
+
key_paths = [key_paths].flatten
|
81
118
|
|
82
|
-
key_paths
|
83
|
-
|
84
|
-
|
85
|
-
|
119
|
+
key_paths.each do |key_path|
|
120
|
+
registered = immediate_observers_registry.registered?(target, key_path)
|
121
|
+
|
122
|
+
immediate_observers_registry.add(target, key_path, &block)
|
123
|
+
|
124
|
+
# We need to first register the block, and then call addObserver, because
|
125
|
+
# observeValueForKeyPath will fire immedeately.
|
126
|
+
if not registered
|
127
|
+
target.addObserver(immediate_observers_registry, forKeyPath:key_path, options: IMMIDEATE_OPTIONS, context:nil)
|
128
|
+
end
|
86
129
|
end
|
87
130
|
end
|
88
131
|
|
89
|
-
def
|
90
|
-
|
132
|
+
def unobserve(target = self, key_paths)
|
133
|
+
remove_from_registry_if_exists(target, key_paths, observers_registry)
|
134
|
+
end
|
135
|
+
|
136
|
+
def unobserve!(target = self, key_paths)
|
137
|
+
remove_from_registry_if_exists(target, key_paths, immediate_observers_registry)
|
91
138
|
end
|
92
139
|
|
93
|
-
|
140
|
+
def unobserve_all
|
141
|
+
observers_registry.each_key_path do |target, key_path|
|
142
|
+
target.removeObserver(observers_registry, forKeyPath:key_path)
|
143
|
+
end
|
94
144
|
|
95
|
-
|
96
|
-
|
97
|
-
blocks = key_paths[key_path] || []
|
98
|
-
blocks.each do |block|
|
99
|
-
args = [change[NSKeyValueChangeOldKey], change[NSKeyValueChangeNewKey]]
|
100
|
-
args << change[NSKeyValueChangeIndexesKey] if collection?(change)
|
101
|
-
block.call(*args)
|
145
|
+
immediate_observers_registry.each_key_path do |target, key_path|
|
146
|
+
target.removeObserver(immediate_observers_registry, forKeyPath:key_path)
|
102
147
|
end
|
148
|
+
|
149
|
+
observers_registry.remove_all
|
150
|
+
immediate_observers_registry.remove_all
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
def observers_registry
|
155
|
+
@observers_registry ||= Registry.new
|
103
156
|
end
|
104
157
|
|
105
|
-
def
|
106
|
-
|
158
|
+
def immediate_observers_registry
|
159
|
+
@immediate_observers_registry ||= Registry.new([:new])
|
107
160
|
end
|
108
161
|
|
162
|
+
def remove_from_registry_if_exists(target, key_paths, registry)
|
163
|
+
key_paths = [key_paths].flatten
|
164
|
+
|
165
|
+
key_paths.each do |key_path|
|
166
|
+
if registry.registered?(target, key_path)
|
167
|
+
target.removeObserver(registry, forKeyPath:key_path)
|
168
|
+
registry.remove(target, key_path)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
109
172
|
end
|
110
173
|
end
|