-->

Object initialization in RubyMotion

2019-09-17 17:05发布

问题:

I am new to RubyMotion and trying to understand how object initialization works. Suppose a simple class with one class and one instance method:

class Something
  def self.getSomething
    BubbleWrap::HTTP.post("http://example.com") do |response|
      p response
    end
  end

  def getSomething
    BubbleWrap::HTTP.post("http://example.com") do |response|
      p response
    end
  end
end

Now, why does the following work:

Something.getSomething

And the next snippet not, well, sometimes (ran this snippet and the runtime crashed 8 out of 10 times).

something = Something.new
something.getSomething

I am doing it wrong. Any pointers in the right direction?

回答1:

Use instance variables:

@something = Something.new
@something.getSomething

RubyMotion has a handful of bugs related to local variables and blocks. You're assigning to something and then calling something.getSomething, which then uses BubbleWrap's asynchronous HTTP.post method. The BubbleWrap HTTP block runs, but in the meantime, the method you're calling something.getSomething from has completed execution. Since something is a local variable, it gets garbage collected when the method exits. So when the HTTP request completes and the block is called, the block no longer exists.

You're probably seeing random inconsistent errors (and once in a while an actual working request) because each time, the memory location where the block was stored was reclaimed for something else (or once in a while, it wasn't reclaimed at all so the block is still there). None of this happens when you use an instance variable instead, because when the calling method finishes execution, the instance variable sticks around.

This behavior is definitely unexpected; I know a couple issues have been filed (myself included) to get this fixed.