Какой метод инициализации UIViewController является самым ранним для настройки аналитики?

Ответ

Самый ранний этап для настройки аналитики — это методы инициализации экземпляра класса, а не методы жизненного цикла вью.

Порядок и рекомендуемые методы:

  1. init(nibName:bundle:) — для контроллеров, создаваемых программно.
  2. init?(coder:) — для контроллеров, загружаемых из Storyboard или XIB.
  3. awakeFromNib() — вызывается после загрузки всех объектов из архива (только для контроллеров из Storyboard/XIB).

Пример реализации:

class AnalyticsViewController: UIViewController {

    // Для программной инициализации
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        trackEvent("ViewController initialized programmatically")
    }

    // Для инициализации из Storyboard/XIB
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        trackEvent("ViewController initialized from storyboard")
    }

    // Дополнительный ранний метод для Storyboard/XIB
    override func awakeFromNib() {
        super.awakeFromNib()
        trackEvent("ViewController awoke from NIB")
    }

    private func trackEvent(_ message: String) {
        Analytics.shared.log(event: message)
    }
}

Почему не viewDidLoad()? viewDidLoad() вызывается позже, когда вью уже загружена. Для отслеживания самого факта создания контроллера методы инициализации подходят лучше.

Ответ 18+ 🔞

Смотри, народ постоянно путает, когда втыкать аналитику в контроллер. Все лезут в viewDidLoad, как будто там святое место, а потом охуевают, почему события дублируются или вообще не летят.

А вся магия начинается гораздо раньше, в этих ваших методах инициализации, блядь. Это как фундамент закладывать, а не шторы вешать, когда дом ещё не достроен.

Вот тебе священный порядок, куда совать нос:

  1. init(nibName:bundle:) — это когда ты контроллер из воздуха материализуешь, кодом, без всяких сторибордов. Прямо в коде: let vc = MyVC().
  2. init?(coder:) — а это уже для тех, кто любит визуальный дизайн. Срабатывает, когда система разворачивает твой контроллер из архива (сториборд или xib-файл).
  3. awakeFromNib() — финальный аккорд для сторибордных ребят. Вызывается, когда все аутлеты и экшены уже привязаны, но вьюха ещё не нарисовалась.

Вот, смотри, как это выглядит в коде, чтоб не быть пиздаболом:

class AnalyticsViewController: UIViewController {

    // Для ручного создания, из пальца
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        trackEvent("ViewController initialized programmatically")
    }

    // Для красотулей из Interface Builder
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        trackEvent("ViewController initialized from storyboard")
    }

    // Финальный пинок для сторибордных объектов
    override func awakeFromNib() {
        super.awakeFromNib()
        trackEvent("ViewController awoke from NIB")
    }

    private func trackEvent(_ message: String) {
        Analytics.shared.log(event: message)
    }
}

А теперь главный вопрос: нахуй не viewDidLoad()? Да потому что viewDidLoad — это уже когда вьюха загрузилась, жизненный цикл пошёл, а нам-то надо засечь сам момент, когда контрлер родился, епта! Как младенец — сначала он появляется на свет (init), потом приходит в сознание (awakeFromNib), а уж потом начинает ползать и хулиганить (viewDidLoad). Логично же, блядь?