Мгновенный просмотр контроллера просмотра из раскадровки против создания нового экземпляра
Какова функциональная разница между созданием экземпляра View Controller из раскадровки и созданием нового экземпляра? Например:
#import "SomeViewController.h"
...
SomeViewController *someViewController = [SomeViewController new];
против
#import "SomeViewController.h"
...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];
В любом случае, someViewController
эффективно то же самое?
Ответы
Ответ 1
Основное отличие заключается в том, как создаются экземпляры вашего UIViewController
.
Во втором случае все представления, созданные вами в раскадровке, будут автоматически создаваться для вас, и все выходы и действия будут настроены так, как вы указали в раскадровке.
В первом случае это не происходит; вы просто получаете необработанный объект. Вам нужно будет выделить и создать экземпляр всех ваших подзонов, выложить их с помощью ограничений или иным образом и самостоятельно подключить все выходы и действия. Apple рекомендует сделать это, переопределив метод loadView
UIViewController
.
Ответ 2
Во втором случае контроллер просмотра загрузит свой вид из раскадровки, и вы будете счастливы.
В первом случае это не будет. Если вы не сделали другие шаги (например, переопределить loadView
или viewDidLoad
или создать xib с именем SomeViewController.xib
), вы просто получите пустой белый вид и будете грустны.
Ответ 3
Это не одно и то же. В раскадровке у вас, вероятно, есть элементы интерфейса. У них могут быть ограничения и свойства, установленные через раскадровку. Когда вы создаете экземпляр viewcontroller через раскадровку, вы получаете все инструкции о том, где находятся эти подпункты и каковы их свойства. Если вы просто скажете [SomeViewController new]
, вы не получите все инструкции, которые имеет раскадровка для контроллера вида.
Хорошим тестом будет добавить UIViewController в раскадровку и перетащить на него красный вид. Создайте его с помощью обоих методов и посмотрите, какие различия существуют.
Ответ 4
В Swift вы можете сделать то же самое с
var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
Вам нужно будет указать Идентификатор в раскадровке в SomeViewController и отметьте галочкой значение Использовать идентификатор раскадровки
Ответ 5
simple swift 3 extension
fileprivate enum Storyboard : String {
case main = "Main"
}
fileprivate extension UIStoryboard {
static func loadFromMain(_ identifier: String) -> UIViewController {
return load(from: .main, identifier: identifier)
}
static func load(from storyboard: Storyboard, identifier: String) -> UIViewController {
let uiStoryboard = UIStoryboard(name: storyboard.rawValue, bundle: nil)
return uiStoryboard.instantiateViewController(withIdentifier: identifier)
}
}
// MARK: App View Controllers
extension UIStoryboard {
class func loadHomeViewController() -> HomeViewController {
return loadFromMain("HomeViewController") as! HomeViewController
}
}
Ответ 6
Если вы не хотите создавать экземпляр нового VC с помощью instantiateViewControllerWithIdentifier
, но обращаетесь к экземпляру, созданному раскадровкой из AppDelegate:
- создать свойство в AppDelegate.h, поэтому он будет доступен из классов, используя его
@property (nonatomic, strong) myViewControllerClass*vC;
- in
viewDidLoad
внутри myViewControllerClass.m Я обращаюсь к общему экземпляру AppDelegate и передаю свойство self: [AppDelegate sharedInstance].vC = self;
Мне пришлось использовать это решение в сложной раскадровке и до сих пор не может понять, что я не могу найти простой способ получить доступ ко всем (или, по крайней мере, тем, которые мне нужны) объектам в раскадровке, просто обратившись к их идентификаторам.
Ответ 7
Еще одна вещь, которую нужно проверить, - это если диспетчер представлений, который бросает ошибку, имеет идентификатор storyboardIdentifier, вы можете проверить xib файл раскадровки.
идентификатор отсутствовал в моем случае, ошибка прекратилась, когда я добавил его