Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift extension for selected class instance

In Objective-C category, you can bring in the extended capability introduced by the category methods by including the header of the category in your class.

It seems like all Swift extensions are automatically introduced without import. How do you achieve the same thing in Swift?

For example:

extension UIView {
  // only want certain UIView to have this, not all
  // similar to Objective-C, where imported category header
  // will grant the capability to the class
  func extraCapability() {

  }
}
like image 753
Boon Avatar asked Jun 07 '16 14:06

Boon


2 Answers

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.

like image 119
Daniel Avatar answered Oct 23 '22 09:10

Daniel


You can make extensions private for a particular class by adding private before the extension like so

private extension UIView {

  func extraCapability() {

  }
}

This will mean it can only be used in that particular class. But you will need to add this to each class that requires this extension. As far as I know there is no way to import the extension like you can in Obj-c

like image 35
AdamM Avatar answered Oct 23 '22 10:10

AdamM