gpt4 book ai didi

ios - 如何在 Swift 中获取 UIStoryboard 数组?

转载 作者:搜寻专家 更新时间:2023-11-01 06:16:17 26 4
gpt4 key购买 nike

我发现我的 Storyboard 变得很复杂,所以决定把它拆分成不同的 Storyboard。但是我想自由地实例化一个 UIViewController,无论我把 View Controller 放在哪里。这样,我可以在 View Controller 从 Storyboard 到 Storyboard 之间移动,而不需要记住我把 View Controller 放在哪里,而且我也根本不必更新代码,因为它们都使用相同的代码来实例化具有该名称的相同 View Controller ,无论它位于何处。

因此,我想像这样创建 UIViewController 的扩展:

extension UIViewController {

func instantiate (named: String?, fromStoryboard: String? = nil) -> UIViewController? {
guard let named = named else { return nil; }
if let sbName = fromStoryboard {
let sb = UIStoryboard(name: sbName, bundle: nil);
return sb.instantiateViewController(withIdentifier: named);
}
else {
for sb in UIStoryboard.storyboards {
if let vc = sb.instantiateViewController(withIdentifier: named) {
return vc;
}
}
}
return nil;
}

问题是,我无法在任何地方找到返回 Storyboard实例列表的属性/方法,如 .storyboards 。有什么解决方法吗?我知道我可能有一个 Storyboard名称的静态列表,但那样的话,扩展就不会是动态的并且独立于项目。

有人可以帮忙吗?谢谢。

编辑:

结合accepted answer并从here回答安全地实例化 viewcontroller(如果找不到则返回 nil),这是我的代码:

UIStoryboard+Storyboards.swift:

extension UIStoryboard {

static var storyboards : [UIStoryboard] {
let directory = Bundle.main.resourcePath! + "/Base.lproj"
let allResources = try! FileManager.default.contentsOfDirectory(atPath: directory)
let storyboardFileNames = allResources.filter({ $0.hasSuffix(".storyboardc" )})
let storyboardNames = storyboardFileNames.map({ ($0 as NSString).deletingPathExtension as String })
let storyboardArray = storyboardNames.map({ UIStoryboard(name: $0, bundle: Bundle.main )})
return storyboardArray;
}

func instantiateViewControllerSafe(withIdentifier identifier: String) -> UIViewController? {
if let availableIdentifiers = self.value(forKey: "identifierToNibNameMap") as? [String: Any] {
if availableIdentifiers[identifier] != nil {
return self.instantiateViewController(withIdentifier: identifier)
}
}
return nil
}

}

UIViewController+Instantiate.swift:

extension UIViewController {

static func instantiate (named: String?, fromStoryboard: String? = nil) -> UIViewController? {
guard let named = named else { return nil; }
if let sbName = fromStoryboard {
let sb = UIStoryboard(name: sbName, bundle: nil);
return sb.instantiateViewControllerSafe(withIdentifier: named);
}
else {
for sb in UIStoryboard.storyboards {
if let vc = sb.instantiateViewControllerSafe(withIdentifier: named) {
return vc;
}
}
}
return nil;
}
}

所有 Storyboard文件必须位于 Base.lproj 文件夹中。

我知道,就运行时间而言,这不是最高效的代码。但就目前而言,它很容易被理解,我可以接受。 :) 感谢所有提供帮助的人!

最佳答案

Storyboard通常设置为本地化,因此您应该在包资源目录的 Base.lproj 子目录中查找它们。 Storyboard被编译成扩展名为 .storyboardc 的文件,因此您应该查找具有该后缀的文件并将其剥离。

let directory = Bundle.main.resourcePath! + "/Base.lproj"
let allResources = try! FileManager.default.contentsOfDirectory(atPath: directory)
let storyboardFileNames = allResources.filter({ $0.hasSuffix(".storyboardc" )})
let storyboardNames = storyboardFileNames.map({ ($0 as NSString).deletingPathExtension as String })
Swift.print(storyboardNames)

如果您已经创建了特定于设备的 Storyboard(通过将 ~ipad~iphone 添加到 Storyboard文件名中),那么您还需要去掉这些后缀和消除重复项。

请注意,特别是已编译的 Storyboard后缀不是 SDK 的文档部分,因此它可能会在未来版本的 iOS/Xcode 中发生变化。

关于ios - 如何在 Swift 中获取 UIStoryboard 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44320803/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com