Swift Extension for Selected Class Instance

Swift extension for selected class instance

Define a protocol that will serve as a selection, wether the extensions should be available or not:

protocol UIViewExtensions { }

then define an extension for the protocol, but only for subclasses of UIView (the other way around won't work):

extension UIViewExtensions where Self: UIView {
func testFunc() -> String { return String(tag) }
}

A class that is defined to have the protocol will also have the extension:

class A: UIView, UIViewExtensions { }    
A().testFunc() //has the extension

And if it is not defined to have the protocol, it will also not have the extension:

class B: UIView {}    
B().testFunc() //execution failed: MyPlayground.playground:17:1: error: value of type 'B' has no member 'testFunc'

UPDATE

Since protocol extensions don't do class polymorphism, if you need to override functions, the only thing I can think of is to subclass:

class UIViewWithExtensions: UIView {
override func canBecomeFocused() -> Bool { return true }
}
UIViewWithExtensions().canBecomeFocused() // returns true

this could also be combined with the extension, but I don't think it would still make much sense anymore.

Swift: Viewing full class API including extensions

I would say offhand that there's no good way to do it. You'd think that the Symbol Navigator would be the way, but it seems to know nothing of Swift extensions (as opposed to Objective-C categories, which it does know about). Being created entirely with the Objective-C family of languages in mind, Xcode has not yet caught up with the existence and nature of Swift.

Using 'self' in class extension functions in Swift

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
}
}

Extensions in my own custom class

In the case of a class that you create from scratch extensions are a powerful type of documentation through structure. You put the core of your class in the initial definition and then add on extensions to provide additional features. For example, adding adherence to a protocol. It provides locality to the contained code:

struct Foo {
let age: Int
}

extension Foo: CustomStringConvertible {
var description:String { return "age: \(age)" }
}

Could I have put the protocol and computed property in the struct declaration? Absolutely but when you have more than one or two properties it starts to get messy and difficult to read. It's easier to create bugs if the code isn't clean and readable. Using extensions is a great way to stave off the difficulties that come with complexity.

Can a Swift class be extended multiple times with the same methods?

Overriding a single protocol method twice in 2 separate extensions wouldn't work, because the protocol method names would collide. Once compiled, they're all just methods on the same class. With that in mind, perhaps put all the protocol methods in their own extension & call them from within the other ones?

The following could be one general option. Could get messy if you decide to keep adding additional extension functionality.

    class baseClass {
//stuff
}

extension baseClass: myProtocol {

override func myProtocolMethod(args) -> returnType {
//Repeat this in a separate extension & your method names collide
var status: Bool

//protocol method code sets status as appropriate...

return status = true ? optOne(status) : optTwo(status)

}

func optOne(status:Bool) -> returnType{
//do the 'true' thing
return returnType
}

func optTwo(status:Bool) -> returnType{
//do the 'false' thing
return returnType
}
}

extension baseClass {
var oneExtension = myProtocolMethod(someArg)
}

extension baseClass {
var twoExtension = myProtocolMethod(someArg)
}


Related Topics



Leave a reply



Submit