结合Swift的 protocol & Generic 对UITableIView和UICollectionView的复用可以GIt搜索Reusable
从UIStoryboard加载UIViewController类似
首先要保证UIViewController的storyboardID 和 类名相同
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
网友评论