Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

Using 'self' in class extension functions in Swift

I'm looking to be able to pull out an instance of a UIView subclass from a Nib.

I'd like to be able to call MyCustomView.instantiateFromNib() and have an instance of MyCustomView. I'm almost ready to just port the working Objective-C code I have via the bridging header, but figured I'd try the idiomatic approach first. That was two hours ago.

extension UIView {
    class func instantiateFromNib() -> Self? {

        let topLevelObjects = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)

        for topLevelObject in topLevelObjects {
            if (topLevelObject is self) {
                return topLevelObject
            }
        }

        return nil
    }
}

Now if (topLevelObject is self) { is wrong because "Expected type after 'is'". What I've tried after that shows a lot about what I don't understand about the Swift type system.

  • if (topLevelObject is Self) {
  • if (topLevelObject is self.dynamicType) {
  • if (topLevelObject is self.self) {
  • A million other variations that are not even wrong.

Any insight is appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Using the approach from How can I create instances of managed object subclasses in a NSManagedObject Swift extension? you can define a generic helper method which infers the type of self from the calling context:

extension UIView {

    class func instantiateFromNib() -> Self? {
        return instantiateFromNibHelper()
    }

    private class func instantiateFromNibHelper<T>() -> T? {
        let topLevelObjects = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)

        for topLevelObject in topLevelObjects {
            if let object = topLevelObject as? T {
                return object
            }
        }
        return nil
    }
}

This compiles and works as expected in my quick test. If MyCustomView is your UIView subclass then

if let customView = MyCustomView.instantiateFromNib() {
    // `customView` is a `MyCustomView`
    // ...
} else {
    // Not found in Nib file
}

gives you an instance of MyCustomView, and the type is inferred automatically.


Update for Swift 3:

extension UIView {

    class func instantiateFromNib() -> Self? {
        return instantiateFromNibHelper()
    }

    private class func instantiateFromNibHelper<T>() -> T? {
        if let topLevelObjects = Bundle.main.loadNibNamed("CustomViews", owner: nil, options: nil) {
            for topLevelObject in topLevelObjects {
                if let object = topLevelObject as? T {
                    return object
                }
            }
        }
        return nil
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...