如何检查具有指定标识符的视图控制器是不是可用

Posted

技术标签:

【中文标题】如何检查具有指定标识符的视图控制器是不是可用【英文标题】:How to check View controller is available with specified identifier or not如何检查具有指定标识符的视图控制器是否可用 【发布时间】:2019-12-11 05:54:48 【问题描述】:

在我的应用程序标识符中来自服务器,我们将它们用作视图控制器标识符。在这里,我想检查具有指定标识符的 ViewController 是否可用。如果可用,则仅推送到该控制器,否则仅返回。我写了如下代码。

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

if let vc1 = (self.storyboard?.instantiateViewController(withIdentifier:identifier))
    let navi = BaseNaviViewController(rootViewController:vc1)
    navi.navigationBar.tintColor = .white
    navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)

else 
    return

这里我收到一个错误提示

由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'Storyboard () 不包含带有标识符的视图控制器 'abc''

【问题讨论】:

【参考方案1】:

终于有办法了

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
    

我已经使用了这种方法,如下所示

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

 if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateVC(withIdentifier: identifier) 
          let navi = BaseNaviViewController(rootViewController:viewController)
                 navi.navigationBar.tintColor = .white
                 navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
                 sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)
        
        else 

            ServerService.ShowAlertMessage(ErrorMessage: "No controller Available", title: "Oops . . . !", view: self)
        

【讨论】:

【参考方案2】:

如果标识符不存在,此方法将返回 nil,因此只需使用 NSAssert 检查即可。

【讨论】:

能否提供 NSAssert 的详细代码? @Anil 方法将返回 nil -> 它会使您的应用崩溃。【参考方案3】:

如果我没记错的话,您正在尝试按照 storyboard identifier 实现动态屏幕重定向,并且您从 Array 中获得了 storyboard_id

之前,我曾处理过同样的需求,也遇到过同样的问题。不幸的是,如果storyboard_id 不存在,则没有解决方案来阻止崩溃。

当时我已经添加了一个空的storyboard_id,如果目标ViewController不可用,在重定向之前,我检查了storyboard_id是否为空,然后跳过重定向代码。

代码:

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

if identifier.count == 0
    return
else
    let vc1 = (self.storyboard?.instantiateViewController(withIdentifier:identifier))
    let navi = BaseNaviViewController(rootViewController:vc1)
    navi.navigationBar.tintColor = .white
    navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)

谢谢

【讨论】:

Hitesh 感谢您的解决方案。在我的情况下,标识符不为空/空。但是具有该标识符的控制器在情节提要中不可用。我想你明白了我的想法。 标识符不为空/null:看起来,如果我们提供了不正确的故事板 ID,那么它将使我们的应用程序崩溃。我已尽一切努力解决崩溃,但没有运气。【参考方案4】:

您可以像这样将所有标识符存储在枚举中:

enum Identifier: String 
    case viewcontroller

    var storyboardName: String 
        switch self 
        case .viewcontroller : return "Main"
        
    


if let validIdentifier = Identifier(rawValue: "vc") 
    let storyboard = UIStoryboard(name: validIdentifier.storyboardName, bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: validIdentifier.rawValue)

【讨论】:

以上是关于如何检查具有指定标识符的视图控制器是不是可用的主要内容,如果未能解决你的问题,请参考以下文章

Storyboard 不包含仅在 TestFlight 上具有标识符的视图控制器

从情节提要“Main”中实例化具有标识符“UIViewController-ZWG-5q-24I”的视图控制器,但没有获得 UITableView。

如何从标签栏控制器执行 show segue?

UIButton - NSInternalInconsistencyException - 无法将具有标识符 Cell2 的单元格出列

如何使用 LGSideMenuController 推送带有情节提要标识符的视图控制器?

如何在情节提要中为视图控制器提供“标识符”?