简体   繁体   中英

Custom UIView for an UIViewController in Swift

I use code to create the view (with subviews) for UIViewController 's this is how I do it:

  1. override loadView()

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

and here is how I create my custom view:

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
}

I do this for all my View Controllers and I am looking for more elegant way, because this process is repetitive, so is there any solution for make that generic for example, create a super abstract class, or create an extension for UIViewController and UIView, Protocols ? I am new for swift and I think that Swift can have a better elegant solution with it's modern patterns

If you are wanting to create many different controllers with custom view classes my recommended solution would be along these lines:

First implement a custom view subclass the way you want to be able to use it, here I have used the one you had in your question. You can then subclass this anywhere you need it and just override the relevant methods.

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
    }

}

Then create a generic custom view controller that allows specification of a class as a generic parameter so that you can easily create a controller with a custom view 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)
    }

}

Then if you wanted to define a new custom view and create a controller that uses it you can simply:

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

...

let controller = CustomViewController<AnotherCustomView>()

Boom!

If you wanted you could even typealias this new controller type to make it even more elegant:

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

...

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM