Ответ 1
В iOS 9 или новее можно использовать:
viewController.loadViewIfNeeded()
Документы: https://developer.apple.com/reference/uikit/uiviewcontroller/1621446-loadviewifneeded
Недавно я написал код, в котором я пытался ссылаться на выход на UIViewController
, который я только что создавал с помощью [storyboard instantiateViewControllerWithIdentifier]
, и изменил подпункт, на который указывает выход, перед тем как представить ViewController
. Это не сработало, потому что представление ViewController
еще не загрузило свои подпрограммы, включая тот, на который ссылался мой выход, поэтому свойство просто дало мне нулевой указатель.
После (с некоторой борьбой) отслеживания причины моей проблемы в отладчике я разобрался и узнал через ответы, такие как этот, что я могу вызвать представление для загрузки своих подзонов без отображения, вызвав геттер myViewController.view
. После этого я могу без проблем получить доступ к моей розетке.
Это явный хак, правда, и Xcode - совершенно правильно - ему не нравится, и сердито протестует с этим предупреждением:
Результат доступа к свойствам не используется - геттеры не должны использоваться для побочных эффектов
Есть ли альтернативный способ для неаккуратных альтернатив, который не связан с использованием .view
getter? В качестве альтернативы существуют канонические/идиоматические шаблоны для этого сценария, включающие нечто вроде динамического добавления обработчика, который будет вызываться сразу после загрузки подвью?
Или стандартное решение просто заменить myViewController.view
на [myViewController view]
, чтобы закрыть предупреждение Xcode, а затем жить с хаком?
В iOS 9 или новее можно использовать:
viewController.loadViewIfNeeded()
Документы: https://developer.apple.com/reference/uikit/uiviewcontroller/1621446-loadviewifneeded
Я согласен с тем, что следует избегать форсирования представления для загрузки, но я столкнулся с ситуацией, когда это казалось единственным разумным решением проблемы (появление UINavigationController, содержащего UISearchController, который еще не был вызван, вызывает неприятную консоль, предупреждающую).
То, что я сделал, это использовать новый API iOS9 loadViewIfNeeded, а для pre-iOS9 используется viewController.view.alpha = 1.0. Конечно, хороший комментарий выше этого кода не позволит вам (или кому-то еще) удалять этот код позже, думая, что он не нужен.
Тот факт, что Apple теперь предоставляет эти API-сигналы, может понадобиться время от времени.
объединил ответы 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
}
Если я правильно вас понимаю, я думаю, есть еще одно довольно стандартное решение: переместите модификацию/конфигурацию выхода в метод viewDidLoad
(из недавно созданного VC).
Тема также обсуждается в этом question.
Это потребует некоторой реструктуризации, но это может дать вам "более чистый" дизайн с точки зрения MVC, если ваш входящий VC обработает свою собственную конфигурацию, и это позволит избежать "вы никогда не должны называть этот метод напрямую" стриктура на loadView
.
Вы можете вызвать [myViewController loadView]
, чтобы явно загрузить представление, вместо того, чтобы злоупотреблять геттером .view
. Геттер .view
на самом деле вызывает loadView
при необходимости при вызове.
Это еще не очень хорошее решение, так как раздел UIView Documentation в loadView
явно указывает, что
Вы никогда не должны вызывать этот метод напрямую