class Elevate::Task

Public Class Methods

new(definition, controller, active_tasks) click to toggle source
# File lib/elevate/task.rb, line 3
def initialize(definition, controller, active_tasks)
  @definition = definition
  @controller = WeakRef.new(controller)
  @active_tasks = active_tasks
  @operation = nil
  @channel = Channel.new(method(:on_update))
  @args = nil
  @timer = nil
end

Public Instance Methods

cancel() click to toggle source
# File lib/elevate/task.rb, line 13
def cancel
  if @operation
    @operation.cancel

    if @timer
      @timer.invalidate
    end
  end
end
name() click to toggle source
# File lib/elevate/task.rb, line 23
def name
  @definition.name
end
start(args) click to toggle source
# File lib/elevate/task.rb, line 27
def start(args)
  @operation = ElevateOperation.alloc.initWithTarget(@definition.handlers[:background],
                                                     args: args,
                                                     channel: WeakRef.new(@channel))

  @operation.addObserver(self, forKeyPath: "isFinished", options: NSKeyValueObservingOptionNew, context: nil)
  queue.addOperation(@operation)
  @active_tasks << self

  @args = args

  if interval = @definition.options[:timeout_interval]
    @timer = NSTimer.scheduledTimerWithTimeInterval(interval,
                                                    target: self,
                                                    selector: :"on_timeout:",
                                                    userInfo: nil,
                                                    repeats: false)
  end

  performSelectorOnMainThread(:on_start, withObject: nil, waitUntilDone: false)
end

Private Instance Methods

error_handler_for(exception) click to toggle source
# File lib/elevate/task.rb, line 51
def error_handler_for(exception)
  handler_name = exception.class.name
  handler_name = handler_name.split("::").last
  handler_name.gsub!(/Error$/, "")
  handler_name.gsub!(/(.)([A-Z])/) { |m| "#{$1}_#{$2.downcase}" }
  handler_name = "on_" + handler_name.downcase

  handler_name.to_sym
end
invoke(handler_name, *args) click to toggle source
# File lib/elevate/task.rb, line 61
def invoke(handler_name, *args)
  return false if @operation.isCancelled

  block = @definition.handlers[handler_name]
  return false unless block

  @controller.task_args = @args
  @controller.instance_exec(*args, &block)
  @controller.task_args = nil

  true
end
observeValueForKeyPath(path, ofObject: operation, change: change, context: ctx) click to toggle source
# File lib/elevate/task.rb, line 83
def observeValueForKeyPath(path, ofObject: operation, change: change, context: ctx)
  case path
  when "isFinished"
    performSelectorOnMainThread(:on_finish, withObject: nil, waitUntilDone: false)
  end
end
on_finish() click to toggle source
# File lib/elevate/task.rb, line 94
def on_finish
  @operation.removeObserver(self, forKeyPath: "isFinished")
  @active_tasks.delete(self)

  if @timer
    @timer.invalidate
  end

  if exception = @operation.exception
    invoke(error_handler_for(exception), exception) || invoke(:on_error, exception)
  end

  invoke(:on_finish, @operation.result, @operation.exception)
end
on_start() click to toggle source
# File lib/elevate/task.rb, line 90
def on_start
  invoke(:on_start)
end
on_timeout(timer) click to toggle source
# File lib/elevate/task.rb, line 109
def on_timeout(timer)
  @operation.timeout
end
on_update(args) click to toggle source
# File lib/elevate/task.rb, line 113
def on_update(args)
  unless NSThread.isMainThread
    performSelectorOnMainThread(:"on_update:", withObject: args, waitUntilDone: false)
    return
  end

  invoke(:on_update, *args)
end
queue() click to toggle source
# File lib/elevate/task.rb, line 74
def queue
  Dispatch.once do
    $elevate_queue = NSOperationQueue.alloc.init
    $elevate_queue.maxConcurrentOperationCount = 1
  end

  $elevate_queue
end