Методы жизненного цикла ProMotion вышли из строя

В последние пару недель я терял рассудок из-за очень странного поведения ProMotion / RedPotion.

Я сузил странное поведение до, казалось бы, неправильного выполнения методов жизненного цикла ProMotion и вызова API.

У меня есть экран, который будет получать информацию из моего API и отображать изображение на основе URL-адреса изображения, возвращенного из API. Я упростил свой проект до экрана, модели и таблицы стилей следующим образом:

TestScreen:

class TestScreen < PM::Screen
  title "Your title here"
  stylesheet TestScreenStylesheet

  def on_load
    mp "ran on_load"
    @face_image = append!(UIImageView, :face_image)
    mp "getting data from API"
    Face.get(1) do |response, face|
      if response.success?
        mp "face returned from API:"
        mp face.inspect
        @face = face
      else
        @face = [{attributes: {name: "No faces found"}}]
      end
    end
    mp "should have printed data obtained from API"
  end

  def will_appear
    mp "ran on_will_appear"
    mp "face in will_appear:"
    if @face
      rmq(:face_image).attr(remote_image: @face.picture)
    else
      mp "@face is nil!!!"
    end
  end

end

Стили:

class TestScreenStylesheet < ApplicationStylesheet

  def setup
  end

  def root_view(st)
    st.background_color = color.white
  end

  def face_image(st)
    st.frame = {l: 30, t: 140, w: 250, h: 250}
    st.placeholder_image = image.resource("placeholder_image.png")
  end
end

Модель:

class Face
  attr_accessor :id, :name, :description, :local_description, :picture, :bio_picture, :star_ranking, :status, :facetype_id, :answers

  def initialize(response)
    @id = response[:data][0][:id]
    @name = response[:data][0][:attributes][:name]
    @description = response[:data][0][:attributes][:description]
    @local_description = response[:data][0][:attributes][:local_description]
    @picture = response[:data][0][:attributes][:picture]
    @bio_picture = response[:data][0][:attributes][:bio_picture]
    @star_ranking = response[:data][0][:attributes][:star_ranking]
    @status = response[:data][0][:attributes][:status]
    @facetype_id = response[:data][0][:attributes][:facetype_id]
    @answers = response[:data][0][:attributes][:answers]

  end

  def self.get(category_id,&callback)
    ApiClient.client.get "random_face?mycategory=#{category_id}" do |response|
      model = nil
      if response.success?
        model = self.new(response.object)
      end
      callback.call(response, model)
    end
  end

end

Я поместил команды распечатки (mp), чтобы я мог выяснить, что выполняется, и, как вы можете видеть из результатов ниже, все вышло из строя:

"ran on_load"
"getting data from API"
"should have printed data obtained from API"
"ran on_will_appear"
"face in will_appear:"
"@face is nil!!!"
"face returned from API:"
"#<Face:0x113c37c90 @id=\"1\" @name=\"Leonel Messi\" @description=\"Leonel Messi es un jugador portugués de fútbol, 4 veces ganador del Balón de Oro\" @local_description=\"translation missing: en.Leonel Messi_description\" @picture=\"default_url\" @bio_picture=\"default_url\" @star_ranking=1 @status=\"active\" @facetype_id=nil @answers=\"[\\\"Kun Aguero\\\", \\\"Nicolas Shevchenko\\\", \\\"Leonel Messi\\\", \\\"Clarence Seedorf\\\"]\">"

Метод on_load срабатывает первым, как и ожидалось, но вызов API RIGHT IN MIDDLE метода on_load срабатывает последним. Поэтому атрибут изображения, который я пытаюсь установить в методе view_did_load, равен нулю и не работает.

Я родом из Rails, и я новичок в RubyMotion / ProMotion / RedPotion, поэтому я могу ошибаться, но, похоже, что-то здесь не так.

1 ответ

Решение

Как указывал Эндрюхейвенс здесь:

https://github.com/infinitered/redpotion/issues/164

причина, по которой это происходит, заключается в том, что мой вызов API является асинхронным, поэтому он не завершит выполнение и установит переменную экземпляра вовремя, чтобы метод will_appear использовал ее (он все равно будет равен нулю во время выполнения will_appear).

Чтобы правильно установить атрибуты, они должны быть установлены ПОСЛЕ завершения API-вызова, например, в самом обратном вызове, например так:

...

if response.success?
  mp "face returned from API:"
  mp face.inspect
  @face = face
  rmq(:face_image).attr(remote_image: @face.picture)
else

...

тогда все будет работать нормально.

Надеюсь, это сэкономит кому-то часы на устранение неисправностей.

Другие вопросы по тегам