美文网首页
Swift 从 UIStoryboard 加载 UIViewCo

Swift 从 UIStoryboard 加载 UIViewCo

作者: fd5657ed541e | 来源:发表于2017-06-18 17:42 被阅读1706次

结合Swift的 protocol & Generic 对UITableIView和UICollectionView的复用可以GIt搜索Reusable
从UIStoryboard加载UIViewController类似
首先要保证UIViewController的storyboardID 和 类名相同

image.png

Talk is cheap, show me the code...

/// 获取类名
protocol Identifiable {
    static var identifier: String { get }
}

/// 自己默认实现 返回类名
extension Identifiable {
    static var identifier: String { return "\(self)" }
}

/// UIViewController 类型免费获得了 identifier 属性
extension UIViewController: Identifiable {}

/// 核心协议
protocol StoryboardLoader {
    
    /// 占位符, 要加载的 UIViewController 类型
    associatedtype ViewController: UIViewController

    /// 要加载的 UIViewController 实例
    var value: ViewController { get }
}

/// 默认实现
/// RawRepresentable , Self.RawValue == String 这个对应storyboard名字, 如 main.sb, order.sb
extension StoryboardLoader where Self: RawRepresentable, Self.RawValue == String {
    
    var value: ViewController {
        
        if let vc = UIStoryboard(name: rawValue, bundle: nil)
            .instantiateViewController(withIdentifier: ViewController.identifier)
            as? ViewController {
            return vc
        }
        fatalError("cannot load viewController with storyboard name: \(rawValue), identifier: \(ViewController.identifier)")
    }
}

根据协议的约束很容易就想到 enum最容易实现这个类型,于是有:

enum Storyboard<T: UIViewController>: String, StoryboardLoader {
    /// 占位符类型
    typealias ViewController = T
    case one = "One"
    case another = "Another"
}

或者:

/// ExpressibleByStringLiteral: String 的字面量协议 方便初始化, 更加直观
/// 例如 let sb: Storyboard = "One"
struct Storyboard<T: UIViewController>: RawRepresentable, StoryboardLoader, ExpressibleByStringLiteral {
    
    static var one: StoryboardStruct<T> { return "One" }
    static var another: StoryboardStruct<T> { return "Another" }
    
    typealias ViewController = T
    
    let rawValue: String
    
    init?(rawValue: String) {
        self.rawValue = rawValue
    }
    
    init(stringLiteral value: String) {
        rawValue = value
    }
    
    init(unicodeScalarLiteral value: String) {
        rawValue = value
    }
    
    init(extendedGraphemeClusterLiteral value: String) {
        rawValue = value
    }
}

然后调用:

/// 获取 another.soryboard 里的 AnotherViewController实例
let anotherViewController = Storyboard<AnotherViewController>.another.value
/// 获取 another.soryboard 里的 AnotherTableViewController实例
let anotherTableViewController = Storyboard<AnotherTableViewController>.another.value

Demo 连接
https://github.com/287258813/StoryboardLoader

相关文章

网友评论

      本文标题:Swift 从 UIStoryboard 加载 UIViewCo

      本文链接:https://www.haomeiwen.com/subject/aatwqxtx.html