0

I'm trying to create an extension for loading UIView (and subclasses) from XIBs. The desire is to have the extension return the specific subclass of UIView. Here's what I have thus far:

extension UIView {

    class func instantiateNIB(name: String, bundle: NSBundle? = nil) -> UIView? {
        let nib = UINib(nibName: name, bundle: bundle)
        let views = nib.instantiateWithOwner(nil, options: nil)

        for view in views {
            if let match = view as? UIView {
                return match
            }
        }

        return nil
    }

}

Then:

let spinner: Spinner = Spinner.instantiateNIB("Spinner") as! Spinner
let rater: Rater = Rater.instantiateNIB("Rater") as! Rater

The issue is this method always returns a UIView that needs the forced down casting in a subsequent call. Is it possible to modify it to perform the downcast automatically? For example:

let spinner = Spinner.instantiateNIB(name: "Spinner")
let rater = Rater.instantiateNIB(name: "Rater")
Kevin Sylvestre
  • 37,288
  • 33
  • 152
  • 232

1 Answers1

1

Try this:

extension UIView {

    class func instantiateNIB(name: String, bundle: NSBundle? = nil) -> Self? {
        return instantiateNIB(self, name: name, bundle: bundle)
    }

    private class func instantiateNIB<T>(type: T.Type, name: String, bundle: NSBundle? = nil) -> T? {
        let nib = UINib(nibName: name, bundle: bundle)
        let views = nib.instantiateWithOwner(nil, options: nil)

        for view in views {
            if let match = view as? T {
                return match
            }
        }

        return nil
    }

}
Bannings
  • 10,376
  • 7
  • 44
  • 54