在我的代码中我有这一行,但我想知道是否有办法检查 @“SomeController”是否存在,然后才将它与“ instantiateViewControllerWithIdentifier ”一起使用方法。如果标识符不存在则应用程序崩溃。
如果没有一个好的方法,这不是一个大问题,我可以更加小心,不要指责标识符名称,但我希望我能更优雅地处理它。
UIViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeController"];
答案 0 :(得分:7)
正如汤姆所说,这个问题的最佳解决方案是try-catch块:
@try {
UIViewController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"identifier"];
}
@catch (NSException *exception) {
UIAlertView *catchView;
catchView = [[UIAlertView alloc]
initWithTitle: NSLocalizedString(@"Error", @"Error")
message: NSLocalizedString(@"Identifier not found on SB".", @"Error")
delegate: self
cancelButtonTitle: NSLocalizedString(@"OK", @"Error") otherButtonTitles: nil];
[catchView show];
}
我希望它有所帮助!即使答案真的很晚。
答案 1 :(得分:6)
您可以在valueForKey:
上使用UIStoryboard
。 UIStoryboard
有一个名为" identifierToNibNameMap"的密钥,其值为NSDictionary
,其中UIViewController
位于该故事板中。这个内部NSDictionary
使用视图控制器的名称作为键,因此您可以使用以下代码实际检查故事板中是否存在viewcontroller:
if ([[storyboard valueForKey:@"identifierToNibNameMap"] objectForKey:myViewControllerName]) {
// the view controller exists, instantiate it here
UIViewController* myViewController = [storyboard instantiateViewControllerWithIdentifier:myViewControllerName];
} else {
//the view controller doesn't exist, do fallback here
}
注意:众所周知,Apple会拒绝使用valueForKey:
查询可可类的基础属性的应用。这些底层属性可能在将来的任何时候发生变化,在没有警告的情况下破坏应用功能这些事情没有弃用过程。
答案 2 :(得分:3)
不,没有检查。但是,您不需要。如果标识符不存在,此方法将返回nil
,因此只需使用NSAssert
检查该方法。
编辑其实这是错误的!!这很奇怪......文档的返回值部分与另一部分相矛盾......但答案仍然是最终没有(没有方法来检查是否存在标识符)
答案 3 :(得分:2)
@ Kevin的解决方案有效。这是一个与Swift 3相同的代码片段,我正在使用我的代码:
func instantiateViewController(fromStoryboardName storyboardName: String, withIdentifier identifier: String) -> UIViewController? {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: nil)
if let availableIdentifiers = mainStoryboard.value(forKey: "identifierToNibNameMap") as? [String: Any] {
if availableIdentifiers[identifier] != nil {
if let poiInformationViewController = mainStoryboard.instantiateViewController(withIdentifier: identifier) as? UIViewController {
return viewController
}
}
}
return nil
}
使用此功能如下:
if let viewController = self.instantiateViewController(fromStoryboardName: "YourStoryboardName", withIdentifier: "YourViewControllerStoryboardID") {
// Here you are sure your viewController is available in the Storyboard
} else {
print("Error: The Storyboard with the name YourStoryboardName or the Storyboard identifier YourViewControllerStoryboardID is not available")
}
答案 4 :(得分:1)
您可以使用try-catch异常处理来包装代码,并决定在发生此类异常时如何做出反应。 我使用此方法动态实例化视图控制器,而不必知道它们是在Storyboard还是nib文件中表示。
答案 5 :(得分:0)
迅速4.2。
在下面声明一个扩展名。
macros
在任何地方都可以使用这种方法:
extension UIStoryboard {
func instantiateVC(withIdentifier identifier: String) -> UIViewController? {
// "identifierToNibNameMap" – dont change it. It is a key for searching IDs
if let identifiersList = self.value(forKey: "identifierToNibNameMap") as? [String: Any] {
if identifiersList[identifier] != nil {
return self.instantiateViewController(withIdentifier: identifier)
}
}
return nil
}
}
或
if let viewController = self.storyboard?.instantiateVC(withIdentifier: "yourControllerID") {
// Use viewController here
viewController.view.tag = 0; // for example
}
将“ yourControllerID”替换为控制器的ID。