Is it possible to check whether an identifier exists in a storyboard before instantiating the object?
在我的代码中有这一行,但是我想知道在与" instantiateViewControllerWithIdentifier"方法结合使用之前,是否有办法检查@" SomeController"是否存在。如果标识符不存在,则应用程序崩溃。
如果没有很好的方法,这不是一个大问题,我可以更小心一点,不要用手指指着标识符名称,但是我希望我可以更优雅地处理它。
1 | UIViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeController"]; |
您可以在
1 2 3 4 5 6 | 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拒绝使用
正如Tom所说,解决此问题的最佳方法是try-catch块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @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]; } |
希望对您有所帮助!即使答案确实很晚。
@Kevin的解决方案有效。这是我在代码中使用的与Swift 3相当的函数代码:
1 2 3 4 5 6 7 8 9 10 11 | 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 } |
按如下所示使用此功能:
1 2 3 4 5 | 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") } |
否,对此没有检查。但是,您不需要。如果标识符不存在,则此方法将返回
EDIT其实这是错误的!太奇怪了...文档的返回值部分与另一部分矛盾...但是答案仍然是最终的(没有方法来检查标识符是否存在)
迅速4.2。
在下面声明一个扩展名。
1 2 3 4 5 6 7 8 9 10 11 | extension UIStoryboard { func instantiateVC(withIdentifier identifier: String) -> UIViewController? { //"identifierToNibNameMap" a€" 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 } } |
在任何地方都可以使用这种方法:
1 2 3 4 | if let viewController = self.storyboard?.instantiateVC(withIdentifier:"yourControllerID") { // Use viewController here viewController.view.tag = 0; // for example } |
或
1 2 3 4 | if let viewController = UIStoryboard(name:"yourStoryboardID", bundle: nil).instantiateVC(withIdentifier:"yourControllerID") { // Use viewController here viewController.view.tag = 0; // for example } |
将" yourControllerID"替换为控制器的ID。
您可以使用try-catch异常处理package代码,并确定在发生此类异常时如何做出反应。
我使用此方法动态实例化视图控制器,而不必知道它们是否在情节提要或nib文件中表示。