it-roy-ru.com

Приложение React-Native ios вылетает без отчета

Я создаю приложение для iOS с использованием React Native и пытаюсь протестировать его на телефонах.

Если я подключу свой телефон к компьютеру и "соберусь" прямо на телефоне, приложение будет собрано правильно и откроется/будет работать правильно, без проблем.

Но если я попытаюсь заархивировать его и отправить на телефоны с помощью iTunes Connect TestFlight или Fabric с Crashlytics, приложение вылетает сразу после открытия. Вкратце показывает экран запуска, но не более.

Более того, нет никаких отчетов о сбоях - ни в TestFlight, ни в Crashlytics, ни в XCode, когда я снова подключаю телефон. Так что я работаю в темноте, без какой-либо информации о том, что ломается. Не удалось найти аналогичную проблему в Интернете, поэтому я решил просто спросить. Есть идеи, что может пойти не так?

Пожалуйста, дайте мне знать, есть ли какой-либо код или другие данные, которые вам могут понадобиться. Некоторые из них являются конфиденциальными, но я постараюсь опубликовать примерную версию.

19
Sasha

Как предположил Крис Гейрман, проблема заключалась в ошибке JavaScript. Я не уверен, что люди с похожими проблемами найдут эту ветку, но если они это сделают, вот странная ошибка, которая произошла. 

Я создал простую систему ORM с BaseModel и набором моделей, унаследованных от нее. Конструктор BaseModel выглядел так:

  constructor(props = {}, relations = {}) {
    Object.keys(props).forEach((k) => {
      // Save props to object
      this[k] = props[k];
    });

    this.relations = relations;
    this.className = this.constructor.name;
  }

Эта последняя строка была проблемой. На моем локальном симуляторе, и если я собираю приложение на свой телефон, подключив его, это работает нормально. Например, если модель Message наследуется от BaseModel, вызов var msg = new Message(data, relations); msg.className возвращает Message.

Но кое-что о связывании/архивировании/отправке приложения через TestFlight или Fabric.io минимизирует и uglify JavaScript, так что имена классов изменяются. Так что вместо этого, если я сделаю это - var msg = new Message(data, relations); msg.className - я вернусь к случайному имени переменной, что-то вроде 't'. 

Это было проблемой в моем приложении, потому что моя домашняя страница содержала оператор switch, который работал от className:

iconContent() {
  return {
    Message: {
      icon: <Image style={styles.feedItemIconImage} source={ require('../assets/img/icon_message.png') } />,
      color: c.grass
    }, ...
  }[this.props.className] // from the model item
}

Но 'Message', как и ожидалось, не было значением this.props.className - 't'. И поэтому, если бы я попытался туннелировать, скажем, в значение color, я бы столкнулся с ошибкой, потому что пытался получить доступ к свойству colornull

Почему это не сообщается, я не знаю (я последовал совету Криса и установил Sentry, но все равно, казалось, не сообщал об этой ошибке). 

Но это то, что происходило. Минификация/углификация произошла только когда я установил приложение на телефон через TestFlight/Fabric, и поэтому приложение зависало только в таких условиях. 

Надеюсь, что это спасет любого, кто столкнется с подобной ошибкой, от рвет себе волосы.

12
Sasha

Не уверен, если у вас все еще есть эта проблема - но если у вас есть, я бы рекомендовал проверить Bugsnag для реагировать на собственные сообщения об ошибках - который сообщает о сбоях как на уровне JavaScript, так и на собственных уровнях (Java/какао) ,.

Одной из более сложных проблем, которые необходимо решить при реагировании на собственные аварийные отчеты (как упоминал Саша), является восстановление исходных трасс стека при использовании минификации и/или запутывания - это решается в Bugsnag за счет полной поддержки исходных карт JS, а также символизации iOS и поддержка Android Proguard на нативных слоях.

Дайте мне знать, если это поможет - я основатель @ Bugsnag

1
loopj

Я хотел бы поделиться своим собственным опытом сбоя стадии производства, тогда как на стадии разработки все работало нормально. 

У меня была похожая проблема, вызванная Reactotron logger. Так как я не собираю его на стадии производства, одна строка console.tron.log вывела мое приложение с полной невидимостью. (Это своего рода моя вина, так как мне наплевать на мой линтер с настройкой 'no-console')

Вот фрагмент кода, который я ввел в свой файл корневого уровня, root.js.

  if (__DEV__) {
     ...
     console.tron = Reactotron;
     ...
  }

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

1
eden