rmx 0.6.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 +7 -0
- data/.gitignore +20 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +18 -0
- data/app/app_delegate.rb +5 -0
- data/lib/motion/RMXActionSheet.rb +14 -0
- data/lib/motion/RMXAutoLayoutLabel.rb +19 -0
- data/lib/motion/RMXAutoLayoutScrollView.rb +53 -0
- data/lib/motion/RMXCommonMethods.rb +27 -0
- data/lib/motion/RMXEventsFromProxy.rb +103 -0
- data/lib/motion/RMXExecutionBlock.rb +51 -0
- data/lib/motion/RMXKeyboardHelpers.rb +54 -0
- data/lib/motion/RMXLongTask.rb +133 -0
- data/lib/motion/RMXNavigationController.rb +133 -0
- data/lib/motion/RMXObjectExtensions.rb +10 -0
- data/lib/motion/RMXSegmentedController.rb +71 -0
- data/lib/motion/RMXSetAttributes.rb +34 -0
- data/lib/motion/RMXStrongToWeakHash.rb +46 -0
- data/lib/motion/RMXSynchronizedStrongToWeakHash.rb +40 -0
- data/lib/motion/RMXTableHandler.rb +212 -0
- data/lib/motion/RMXTableViewCell.rb +85 -0
- data/lib/motion/RMXTableViewCellInnerContentView.rb +16 -0
- data/lib/motion/RMXTableViewController.rb +65 -0
- data/lib/motion/RMXUnsafeUnretainedHolder.rb +30 -0
- data/lib/motion/RMXView.rb +84 -0
- data/lib/motion/RMXViewController.rb +65 -0
- data/lib/motion/RMXViewControllerPresentation.rb +127 -0
- data/lib/motion/RMXWeakHolder.rb +36 -0
- data/lib/motion/RMXWeakToStrongHash.rb +39 -0
- data/lib/motion/accessors.rb +29 -0
- data/lib/motion/base.rb +12 -0
- data/lib/motion/env.rb +9 -0
- data/lib/motion/events.rb +61 -0
- data/lib/motion/layout.rb +357 -0
- data/lib/motion/ui.rb +55 -0
- data/lib/motion/util.rb +155 -0
- data/lib/rmx/version.rb +3 -0
- data/lib/rmx.rb +50 -0
- data/resources/Default-568h@2x.png +0 -0
- data/rmx.gemspec +19 -0
- data/spec/main_spec.rb +240 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9cd874bc129e8aef4429698b30fe2bc429c419f0
|
4
|
+
data.tar.gz: dcc6f40d497510993ea5a28c7b6dee46868552e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c900776ee05bcd66a894871dec855c5589493b28effd6e6b227386587402fabd355d194f19cf99fcc1bf140d9225ae22104705f6ffda2a445686f9754e73566f
|
7
|
+
data.tar.gz: e97f08b80bb2568f896af0717cb07124dca1bdd615bdb4590751ef278397a612adc47fa80c5eee2c336704843176b79cf224d60dcf569a251ba38b3601a287df
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Joe Noon
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
RMX
|
2
|
+
-----------------
|
3
|
+
|
4
|
+
#### Extensions and helpers for dealing with various areas of rubymotion and iOS.
|
5
|
+
|
6
|
+
#### [Documentation](https://github.com/joenoon/rmx/wiki/RMX-Documentation)
|
7
|
+
|
8
|
+
#### [CHANGELOG](https://github.com/joenoon/rmx/wiki/CHANGELOG)
|
9
|
+
|
10
|
+
Installation
|
11
|
+
-----------------
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'rmx'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Contributing
|
22
|
+
-----------------
|
23
|
+
|
24
|
+
If you have a better way to accomplish anything this library is doing, please share!
|
25
|
+
|
26
|
+
1. Fork it
|
27
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
28
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
29
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
30
|
+
5. Create new Pull Request
|
31
|
+
|
32
|
+
License
|
33
|
+
-----------------
|
34
|
+
|
35
|
+
Please see [LICENSE](https://github.com/joenoon/rmx/blob/master/LICENSE.txt) for licensing details.
|
36
|
+
|
37
|
+
Author
|
38
|
+
-----------------
|
39
|
+
|
40
|
+
[Joe Noon](https://github.com/joenoon)
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
if ENV['rubymotion']
|
3
|
+
$:.unshift('/Library/RubyMotion/lib')
|
4
|
+
if ENV.fetch('platform', 'ios') == 'ios'
|
5
|
+
require 'motion/project/template/ios'
|
6
|
+
elsif ENV['platform'] == 'osx'
|
7
|
+
require 'motion/project/template/osx'
|
8
|
+
else
|
9
|
+
raise "Unsupported platform #{ENV['platform']}"
|
10
|
+
end
|
11
|
+
require 'bundler'
|
12
|
+
Bundler.require
|
13
|
+
|
14
|
+
Motion::Project::App.setup do |app|
|
15
|
+
# Use `rake config' to see complete project settings.
|
16
|
+
app.name = 'rmx'
|
17
|
+
end
|
18
|
+
end
|
data/app/app_delegate.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class RMXActionSheet < UIActionSheet
|
2
|
+
|
3
|
+
def init
|
4
|
+
s = super
|
5
|
+
self.delegate = self
|
6
|
+
s
|
7
|
+
end
|
8
|
+
|
9
|
+
def actionSheet(actionSheet, clickedButtonAtIndex:buttonIndex)
|
10
|
+
title = actionSheet.buttonTitleAtIndex(buttonIndex)
|
11
|
+
RMX.new(self).trigger(:clickedButton, { :index => buttonIndex, :title => title })
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class RMXAutoLayoutLabel < UILabel
|
2
|
+
def layoutSubviews
|
3
|
+
super
|
4
|
+
if numberOfLines == 0
|
5
|
+
if preferredMaxLayoutWidth != frame.size.width
|
6
|
+
self.preferredMaxLayoutWidth = frame.size.width
|
7
|
+
setNeedsUpdateConstraints
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
def intrinsicContentSize
|
12
|
+
s = super
|
13
|
+
if numberOfLines == 0
|
14
|
+
# found out that sometimes intrinsicContentSize is 1pt too short!
|
15
|
+
s.height += 1
|
16
|
+
end
|
17
|
+
s
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class RMXAutoLayoutScrollView < UIScrollView
|
2
|
+
class FollowView < UIView
|
3
|
+
RMX.new(self).weak_attr_accessor :fittedView
|
4
|
+
def layoutSubviews
|
5
|
+
s = super
|
6
|
+
fittedView.invalidateIntrinsicContentSize
|
7
|
+
fittedView.setNeedsUpdateConstraints
|
8
|
+
fittedView.layoutIfNeeded
|
9
|
+
s
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class FittedView < UIView
|
13
|
+
RMX.new(self).weak_attr_accessor :followView
|
14
|
+
def intrinsicContentSize
|
15
|
+
followView.frame.size
|
16
|
+
end
|
17
|
+
end
|
18
|
+
attr_accessor :contentView
|
19
|
+
def self.fitted_to(parent)
|
20
|
+
followView = FollowView.new
|
21
|
+
followView.userInteractionEnabled = false
|
22
|
+
followView.hidden = true
|
23
|
+
fittedView = FittedView.new
|
24
|
+
fittedView.backgroundColor = UIColor.clearColor
|
25
|
+
fittedView.followView = followView
|
26
|
+
followView.fittedView = fittedView
|
27
|
+
# add a subview to parent called followView
|
28
|
+
RMX::Layout.new do |layout|
|
29
|
+
layout.view parent
|
30
|
+
layout.subviews "x" => followView
|
31
|
+
layout.eqs %Q{
|
32
|
+
x.top == 0
|
33
|
+
x.right == 0
|
34
|
+
x.bottom == 0
|
35
|
+
x.left == 0
|
36
|
+
}
|
37
|
+
end
|
38
|
+
x = new
|
39
|
+
x.contentView = fittedView
|
40
|
+
# add a subview to scrollView called contentView
|
41
|
+
RMX::Layout.new do |layout|
|
42
|
+
layout.view x
|
43
|
+
layout.subviews "x" => fittedView
|
44
|
+
layout.eqs %Q{
|
45
|
+
x.top == 0
|
46
|
+
x.right == 0
|
47
|
+
x.bottom == 0
|
48
|
+
x.left == 0
|
49
|
+
}
|
50
|
+
end
|
51
|
+
x
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RMXCommonMethods
|
2
|
+
|
3
|
+
def rmx_dealloc
|
4
|
+
end
|
5
|
+
|
6
|
+
if RMX::DEBUG_DEALLOC
|
7
|
+
def dealloc
|
8
|
+
p " - dealloc! (queue: #{Dispatch::Queue.current.description})"
|
9
|
+
rmx_dealloc
|
10
|
+
super
|
11
|
+
end
|
12
|
+
else
|
13
|
+
def dealloc
|
14
|
+
rmx_dealloc
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
rmx_object_desc
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
rmx_object_desc
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Proxy class used to hold the actual handlers and contexts of handlers.
|
2
|
+
# When the real class deallocates, all handlers are removed.
|
3
|
+
class RMXEventsFromProxy
|
4
|
+
|
5
|
+
QUEUE = Dispatch::Queue.new("RMXEventsFromProxy")
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@events = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# def rmx_dealloc
|
12
|
+
# off
|
13
|
+
# super
|
14
|
+
# end
|
15
|
+
|
16
|
+
def on(event, opts={}, &block)
|
17
|
+
block ||= proc {}
|
18
|
+
event = event.to_s
|
19
|
+
execution_block = RMXExecutionBlock.new
|
20
|
+
execution_block.strong = opts.delete(:strong)
|
21
|
+
execution_block.limit = opts.delete(:limit)
|
22
|
+
execution_block.queue = opts.delete(:queue)
|
23
|
+
execution_block.meta = opts
|
24
|
+
execution_block.block = block
|
25
|
+
off_block = RMXExecutionBlock.new
|
26
|
+
off_block.block = proc do
|
27
|
+
off(event, execution_block)
|
28
|
+
end
|
29
|
+
QUEUE.sync do
|
30
|
+
@events[event] ||= []
|
31
|
+
@events[event] << execution_block
|
32
|
+
end
|
33
|
+
off_block
|
34
|
+
end
|
35
|
+
|
36
|
+
def now_and_on(event, opts={}, &block)
|
37
|
+
RMX.block_on_main_q(block)
|
38
|
+
on(event, opts, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def off(event=nil, execution_block=nil)
|
42
|
+
QUEUE.sync do
|
43
|
+
if event.is_a?(String) || event.is_a?(Symbol)
|
44
|
+
event = event.to_s
|
45
|
+
if execution_block
|
46
|
+
if events = @events[event]
|
47
|
+
deleted = events.delete(execution_block)
|
48
|
+
if RMX::DEBUG_EVENTS
|
49
|
+
p "remove the one block for the event", "EVENT:", event, "deleted:", deleted
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else
|
53
|
+
deleted = @events.delete(event)
|
54
|
+
if RMX::DEBUG_EVENTS
|
55
|
+
p "remove all blocks for the event", "EVENT:", event, "deleted:", deleted
|
56
|
+
end
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@events.clear
|
60
|
+
if RMX::DEBUG_EVENTS
|
61
|
+
p "remove all blocks for all events"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def trigger(event, *values)
|
69
|
+
QUEUE.async do
|
70
|
+
# if RMX::DEBUG_EVENTS
|
71
|
+
# p "TRIGGER:", event, values, "@events", @events
|
72
|
+
# end
|
73
|
+
event = event.to_s
|
74
|
+
_execution_blocks = @events[event]
|
75
|
+
next unless _execution_blocks
|
76
|
+
execution_blocks = _execution_blocks.dup
|
77
|
+
while execution_blocks.size > 0
|
78
|
+
execution_block = execution_blocks.shift
|
79
|
+
exclusive = execution_block.meta[:exclusive]
|
80
|
+
if exclusive
|
81
|
+
_exclusive = exclusive.dup
|
82
|
+
while _exclusive.size > 0
|
83
|
+
exclude = _exclusive.shift.to_s
|
84
|
+
deleted = @events.delete(exclude)
|
85
|
+
if RMX::DEBUG_EVENTS
|
86
|
+
p "REMOVING DUE TO EXCLUSIVE:", exclude, "FOR EVENT:", event, "deleted:", deleted
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
execution_block.call(*values)
|
91
|
+
if execution_block.dead
|
92
|
+
deleted = _execution_blocks.delete(execution_block)
|
93
|
+
if RMX::DEBUG_EVENTS
|
94
|
+
p "REMOVING DUE TO DEAD:", "FOR EVENT:", event, "deleted:", deleted
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class RMXExecutionBlock
|
2
|
+
attr_accessor :queue, :the_block, :dead, :desc, :strong, :meta, :limit
|
3
|
+
RMX.new(self).weak_attr_accessor :block_owner
|
4
|
+
|
5
|
+
def block=(_block)
|
6
|
+
self.block_owner = _block.owner
|
7
|
+
self.the_block = RMX.safe_block(_block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def actual_queue
|
11
|
+
q = queue
|
12
|
+
if q == :async
|
13
|
+
q = RMXEventsFromProxy::QUEUE
|
14
|
+
elsif q == :main
|
15
|
+
q = Dispatch::Queue.main
|
16
|
+
end
|
17
|
+
q ||= Dispatch::Queue.main
|
18
|
+
q
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(*args)
|
22
|
+
should_cleanup = false
|
23
|
+
if !dead && (blk = the_block) && (o = block_owner) && (q = actual_queue)
|
24
|
+
q.async do
|
25
|
+
blk.call(*args)
|
26
|
+
blk
|
27
|
+
o
|
28
|
+
end
|
29
|
+
else
|
30
|
+
should_cleanup = true
|
31
|
+
end
|
32
|
+
if limit
|
33
|
+
if limit > 0
|
34
|
+
self.limit -= 1
|
35
|
+
end
|
36
|
+
if limit == 0
|
37
|
+
should_cleanup = true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
if should_cleanup
|
41
|
+
self.dead = true
|
42
|
+
self.strong = nil
|
43
|
+
self.meta = nil
|
44
|
+
self.limit = nil
|
45
|
+
self.the_block = nil
|
46
|
+
self.block_owner = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module RMXKeyboardHelpers
|
2
|
+
|
3
|
+
def keyboard_proxy
|
4
|
+
keyboard_proxy_constraints unless @keyboard_proxy_constraints
|
5
|
+
@keyboard_proxy
|
6
|
+
end
|
7
|
+
|
8
|
+
def keyboard_proxy_constraints
|
9
|
+
@keyboard_proxy ||= UIView.new
|
10
|
+
@keyboard_proxy_constraints ||= begin
|
11
|
+
x = {}
|
12
|
+
RMX::Layout.new do |layout|
|
13
|
+
layout.view = view
|
14
|
+
layout.subviews = {
|
15
|
+
"keyboard_proxy" => @keyboard_proxy
|
16
|
+
}
|
17
|
+
x[:bottom] = layout.eq "keyboard_proxy.bottom == #{-RMX.currentKeyboardHeight}"
|
18
|
+
x[:height] = layout.eq "keyboard_proxy.height == 0"
|
19
|
+
end
|
20
|
+
x
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def listenForKeyboardChanged
|
25
|
+
NSNotificationCenter.defaultCenter.addObserver(self, selector:'keyboardChangedInternal:', name:"rmxKeyboardChanged", object:nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
# listens for the rmxKeyboardChanged notification and extracts the userInfo to call a friendlier method
|
29
|
+
def keyboardChangedInternal(notification)
|
30
|
+
if isViewLoaded
|
31
|
+
info = notification.userInfo
|
32
|
+
keyboardChanged(info)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# by default, looks to see if the controller is using the @keyboard_proxy_constraint convention.
|
37
|
+
# if so, sets the constraint's constant and refreshes the layout in the same animationDuration
|
38
|
+
# as the keyboard's animation.
|
39
|
+
#
|
40
|
+
# if you want to do more/other stuff on keyboardChanged, you can override this, call super, or
|
41
|
+
# do everything on your own.
|
42
|
+
def keyboardChanged(info)
|
43
|
+
if constraint = @keyboard_proxy_constraints && @keyboard_proxy_constraints[:height]
|
44
|
+
Dispatch::Queue.main.async do
|
45
|
+
UIView.animateWithDuration(info[:animationDuration], animations: lambda do
|
46
|
+
keyboard_proxy_constraints[:bottom].constant = -RMX.currentKeyboardHeight
|
47
|
+
view.setNeedsUpdateConstraints
|
48
|
+
view.layoutIfNeeded
|
49
|
+
end)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# RMXLongTask encapsulates beginBackgroundTaskWithExpirationHandler/endBackgroundTask:
|
2
|
+
#
|
3
|
+
# RMXLongTask.new("my long task") do |task|
|
4
|
+
# do_something_long
|
5
|
+
# task.end!
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# RMXLongTask.new("my long task") do |task|
|
9
|
+
# do_something_long_async do
|
10
|
+
# # later this long task finishes...
|
11
|
+
# task.end!
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class RMXLongTask
|
16
|
+
attr_accessor :bgTask, :desc
|
17
|
+
|
18
|
+
include RMXCommonMethods
|
19
|
+
|
20
|
+
def self.time_remaining
|
21
|
+
UIApplication.sharedApplication.backgroundTimeRemaining
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.when_all_complete(&block)
|
25
|
+
Dispatch::Queue.main.async do
|
26
|
+
if RMXLongTask.outstanding_tasks.size.zero?
|
27
|
+
RMX.block_on_main_q(block)
|
28
|
+
else
|
29
|
+
RMX.new(RMXLongTask).once(:all_complete) do
|
30
|
+
block.call
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.outstanding_queue
|
37
|
+
Dispatch.once do
|
38
|
+
@outstanding_queue = Dispatch::Queue.new("#{NSBundle.mainBundle.bundleIdentifier}.outstanding.LongTask")
|
39
|
+
end
|
40
|
+
@outstanding_queue
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.outstanding_tasks
|
44
|
+
Dispatch.once do
|
45
|
+
@outstanding_tasks = []
|
46
|
+
end
|
47
|
+
@outstanding_tasks
|
48
|
+
end
|
49
|
+
|
50
|
+
# RMXLongTask.verbose("my long task") { |task| task.end! }
|
51
|
+
def self.verbose(desc=nil, &block)
|
52
|
+
_creator(desc, true, true, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
# RMXLongTask.create("my long task") { |task| task.end! }
|
56
|
+
def self.create(desc=nil, &block)
|
57
|
+
_creator(desc, false, true, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.internal(desc=nil, &block)
|
61
|
+
_creator(desc, false, false, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self._creator(desc=nil, verbose=false, tracking=true, &block)
|
65
|
+
x = new(desc, verbose, tracking)
|
66
|
+
block.weak!.call(x)
|
67
|
+
x
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reset_outstanding_tasks!
|
71
|
+
RMXLongTask.outstanding_queue.sync do
|
72
|
+
size = RMXLongTask.outstanding_tasks.size
|
73
|
+
if size > 0
|
74
|
+
p "WARNING: reset_outstanding_tasks! (was: #{size})"
|
75
|
+
RMXLongTask.outstanding_tasks.removeAllObjects
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def initialize(desc=nil, verbose=false, tracking=true)
|
81
|
+
@verbose = verbose
|
82
|
+
@tracking = tracking
|
83
|
+
@desc = "#{rmx_object_desc} #{desc}"
|
84
|
+
@bgTask = UIApplication.sharedApplication.beginBackgroundTaskWithExpirationHandler(lambda do
|
85
|
+
p "ERROR: #{@desc} didn't call #end! in time!"
|
86
|
+
__end!
|
87
|
+
end)
|
88
|
+
if DEBUG_LONGTASK || @verbose
|
89
|
+
p "CREATED: #{@desc}"
|
90
|
+
end
|
91
|
+
if @tracking
|
92
|
+
RMXLongTask.outstanding_queue.sync do
|
93
|
+
RMXLongTask.outstanding_tasks << self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
def end!
|
100
|
+
if DEBUG_LONGTASK || @verbose
|
101
|
+
p "SUCCESS: #{@desc} ended successfully."
|
102
|
+
end
|
103
|
+
__end!
|
104
|
+
end
|
105
|
+
|
106
|
+
def __end!
|
107
|
+
if @tracking
|
108
|
+
RMXLongTask.outstanding_queue.sync do
|
109
|
+
RMXLongTask.outstanding_tasks.delete(self)
|
110
|
+
RMXLongTask.internal("check for all complete") do |internal_task|
|
111
|
+
Dispatch::Queue.main.async do
|
112
|
+
if RMXLongTask.outstanding_tasks.size.zero?
|
113
|
+
RMX.new(RMXLongTask).trigger(:all_complete)
|
114
|
+
end
|
115
|
+
internal_task.end!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
if @bgTask && @bgTask != UIBackgroundTaskInvalid
|
121
|
+
UIApplication.sharedApplication.endBackgroundTask(@bgTask)
|
122
|
+
@bgTask = UIBackgroundTaskInvalid
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def rmx_dealloc
|
127
|
+
if DEBUG_DEALLOC
|
128
|
+
p "DEALLOC: #{@desc}"
|
129
|
+
end
|
130
|
+
super
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|