Чистый способ принудительного просмотра представлений

Недавно я написал код, в котором я пытался ссылаться на выход на UIViewController, который я только что создавал с помощью [storyboard instantiateViewControllerWithIdentifier], и изменил подпункт, на который указывает выход, перед тем как представить ViewController. Это не сработало, потому что представление ViewController еще не загрузило свои подпрограммы, включая тот, на который ссылался мой выход, поэтому свойство просто дало мне нулевой указатель.

После (с некоторой борьбой) отслеживания причины моей проблемы в отладчике я разобрался и узнал через ответы, такие как этот, что я могу вызвать представление для загрузки своих подзонов без отображения, вызвав геттер myViewController.view. После этого я могу без проблем получить доступ к моей розетке.

Это явный хак, правда, и Xcode - совершенно правильно - ему не нравится, и сердито протестует с этим предупреждением:

Результат доступа к свойствам не используется - геттеры не должны использоваться для побочных эффектов

Есть ли альтернативный способ для неаккуратных альтернатив, который не связан с использованием .view getter? В качестве альтернативы существуют канонические/идиоматические шаблоны для этого сценария, включающие нечто вроде динамического добавления обработчика, который будет вызываться сразу после загрузки подвью?

Или стандартное решение просто заменить myViewController.view на [myViewController view], чтобы закрыть предупреждение Xcode, а затем жить с хаком?

Ответ 2

Я согласен с тем, что следует избегать форсирования представления для загрузки, но я столкнулся с ситуацией, когда это казалось единственным разумным решением проблемы (появление UINavigationController, содержащего UISearchController, который еще не был вызван, вызывает неприятную консоль, предупреждающую).

То, что я сделал, это использовать новый API iOS9 loadViewIfNeeded, а для pre-iOS9 используется viewController.view.alpha = 1.0. Конечно, хороший комментарий выше этого кода не позволит вам (или кому-то еще) удалять этот код позже, думая, что он не нужен.

Тот факт, что Apple теперь предоставляет эти API-сигналы, может понадобиться время от времени.

Ответ 3

объединил ответы Rudolph/Swany для целей развертывания pre ios9

    if #available(iOS 9.0, *) {
        loadViewIfNeeded()
    }
    else {
        // _ = self.view works but some Swift compiler genius could optimize what seems like a noop out
        // hence this perversion from this recipe http://stackoverflow.com/questions/17279604/clean-way-to-force-view-to-load-subviews-early
        view.alpha = 1
    }

Ответ 4

Если я правильно вас понимаю, я думаю, есть еще одно довольно стандартное решение: переместите модификацию/конфигурацию выхода в метод viewDidLoad (из недавно созданного VC).

Тема также обсуждается в этом question.

Это потребует некоторой реструктуризации, но это может дать вам "более чистый" дизайн с точки зрения MVC, если ваш входящий VC обработает свою собственную конфигурацию, и это позволит избежать "вы никогда не должны называть этот метод напрямую" стриктура на loadView.

Ответ 5

Вы можете вызвать [myViewController loadView], чтобы явно загрузить представление, вместо того, чтобы злоупотреблять геттером .view. Геттер .view на самом деле вызывает loadView при необходимости при вызове.

Это еще не очень хорошее решение, так как раздел UIView Documentation в loadView явно указывает, что

Вы никогда не должны вызывать этот метод напрямую