How to Properly Use Class Extensions in Swift

Why we use Extension?

Extensions

Adds functions to your class without subclassing, is very useful in cases where you don´t have the implementation of the class you are trying to extend, example classes that are inside an Framework or library

as is defined in https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html

Extensions add new functionality to an existing class, structure,
enumeration, or protocol type. This includes the ability to extend
types for which you do not have access to the original source code
(known as retroactive modeling). Extensions are similar to categories
in Objective-C. (Unlike Objective-C categories, Swift extensions do
not have names.)

Extensions in Swift can:

Add computed instance properties and computed type properties Define
instance methods and type methods Provide new initializers Define
subscripts Define and use new nested types Make an existing type
conform to a protocol In Swift, you can even extend a protocol to
provide implementations of its requirements or add additional
functionality that conforming types can take advantage of. For more
details, see Protocol Extensions.

NOTE

Extensions can add new functionality to a type, but they cannot
override existing functionality.

Extension Syntax

Declare extensions with the extension keyword:

extension SomeType {
// new functionality to add to SomeType goes here
}

An extension can extend an existing type to make it adopt one or more protocols. To
add protocol conformance, you write the protocol names the same way as
you write them for a class or structure:

extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}

Adding protocol conformance in this way is described in Adding
Protocol Conformance with an Extension.

An extension can be used to extend an existing generic type, as
described in Extending a Generic Type. You can also extend a generic
type to conditionally add functionality, as described in Extensions
with a Generic Where Clause.

Hope this help to clarify you

Swift Advanced - Setting extensions during run time

you can play with runtime modifiers in ObjC freely, but in Swift such kinda pattern is not really common.


NOTE: you can find more information about this in the ObjC Runtime Library, if you are interested.

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.

Class function in swift extension (category)

Yes, it possible and very similar, the main difference is that Swift extensions are not named.

extension UIColor {
class func colorWithHexString(hexString: String) -> UIColor {
// create color from string
// ... some code
return newColor
}
}

Class extension vs. subclassing in Swift?

It's

b)

because adding (stored) properties in a class extension is not supported.

There are two important rules for using extensions:

  • Extensions can add new functionality to a type, but they cannot override existing functionality

  • Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties

Why do we add protocol conformance with extensions?

They are different coding styles. The first option

class Christmas {
...
}

extension Christmas: Merry {
...
}

is cleaner when you're looking at the whole class. You can instantly see all the protocol implementations the class conforms to.

Using the second option you put the implementation of the protocol inside the class mixing it with the class methods. However, if you use

//MARK: - 

the code becomes not less clean, than when you use extensions. For example:

protocol Merry: class {
func celebrate()
}

class Cristmas: NSObject, Merry {
private var santa: AnyObject?

//MARK: - Private Methods
private func callSanta() {
//calling Santa
}

//MARK: - Merry Implementation
func celebrate() {
//celebration starts here
}
}

and when looking at the whole class you clearly see the separation of the protocol implementation:
Sample Image

The functionality of both options is the same.



Related Topics



Leave a reply



Submit