Swift 中 UIViewController 的自定义 UIView

Custom UIView for an UIViewController in Swift

我使用代码为 UIViewController 创建视图(带有子视图),我是这样做的:

  1. 覆盖loadView()

    class MYViewController: UIViewController {
    
    var myView: MyView! { return self.view as MyView }
    
       override func loadView() {
          view = MyView() 
       }
    }
    

这是我创建自定义视图的方式:

class MyView: UIView {

    // MARK: Initialization

    override init (frame : CGRect) {
        super.init(frame : frame)
        addSubviews()
        setupLayout()
    }

    convenience init () {
        self.init(frame:CGRect.zero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("This class does not support NSCoding")
    }

    // MARK: Build View hierarchy

    func addSubviews(){
        // add subviews
    }

    func setupLayout(){
        // Autolayout
    }

    // lazy load views
}

我为我所有的视图控制器都这样做,我正在寻找更优雅的方法,因为这个过程是重复的,所以有没有任何解决方案可以使它变得通用,例如,创建一个超级抽象 class,或者为 UIViewController 和 UIView, Protocols 创建一个扩展?我是 swift 的新手,我认为 Swift 可以有一个更优雅的现代模式解决方案

如果您想创建许多具有自定义视图的不同控制器 classes,我推荐的解决方案如下:

首先实现一个自定义视图 subclass 您希望能够使用它的方式,这里我使用了您在问题中遇到的那个。然后你可以在任何你需要的地方subclass this 并覆盖相关的方法。

class CustomView: UIView {

    // MARK: Initialization

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubviews()
        setupLayout()
    }

    required init() {
        super.init(frame: .zero)
        addSubviews()
        setupLayout()
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("This class does not support NSCoding")
    }

    // MARK: Build View hierarchy

    func addSubviews(){
        // add subviews
    }

    func setupLayout(){
        // Autolayout
    }

}

然后创建一个通用的自定义视图控制器,允许将 class 指定为通用参数,这样您就可以轻松地创建一个带有自定义视图的控制器 class。

class CustomViewController<T: CustomView>: UIViewController {

    var customView: T! { return view as! T }

    override func loadView() {
        view = T()
    }

    init() {
        super.init(nibName: nil, bundle: nil)
    }

}

然后,如果您想定义一个新的自定义视图并创建一个使用它的控制器,您可以简单地:

class AnotherCustomView: CustomView { /* Override methods */ }

...

let controller = CustomViewController<AnotherCustomView>()

轰!

如果您愿意,您甚至可以为这种新的控制器类型输入别名,使其更加优雅:

class AnotherCustomView: CustomView { /* Override methods */ }

...

typealias AnotherCustomViewController = CustomViewController<AnotherCustomView>
let controller = AnotherCustomViewController()