Swift中一个UIViewController的自定义UIView

6

我使用代码创建UIViewController的视图(包括子视图),以下是我的做法:

  1. override 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
}

我为所有的View Controllers 这样做,但我正在寻找更优雅的方法,因为这个过程很重复。所以是否有一种通用的解决方案呢?比如创建一个超级抽象类、或者创建UIViewController和UIView的扩展协议?我刚开始学习Swift,我认为Swift可以用它现代的模式来实现更好的优雅解决方案。

你在这里试图解决的主要问题是什么?是重复的代码吗?如果是这样,为什么不将ViewController和View类作为抽象类,然后进行扩展呢? - JJJ
尝试为此自定义视图使用自定义委托协议。 - Shubham Ojha
我觉得你应该更多地使用storyboards/xibs。我很少需要创建自定义视图。为什么要在代码中使用子视图和布局设置,当你可以在可视化编辑器中更快、更有效地完成呢? - Sulthan
1个回答

11
如果您想创建许多带有自定义视图类的不同控制器,我的推荐解决方案如下:
首先按照您想要使用的方式实现自定义视图子类,这里我使用了您在问题中提到的那个。然后您可以在任何需要它的地方进行子类化,并仅覆盖相关方法。
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 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>()

嘭!

如果您愿意,甚至可以使用typealias将此新控制器类型重命名,使其更加优雅:

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

...

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接