Swift Extension Example

Swift extension example

Creating an extension

Add a new swift file with File > New > File... > iOS > Source > Swift File. You can call it what you want.

The general naming convention is to call it TypeName+NewFunctionality.swift.

Sample Image

Example 1 - Double

Double+Conversions.swift

import Swift // or Foundation

extension Double {

func celsiusToFahrenheit() -> Double {
return self * 9 / 5 + 32
}

func fahrenheitToCelsius() -> Double {
return (self - 32) * 5 / 9
}
}

Usage:

let boilingPointCelsius = 100.0
let boilingPointFarenheit = boilingPointCelsius.celsiusToFahrenheit()
print(boilingPointFarenheit) // 212.0

Example 2 - String

String+Shortcuts.swift

import Swift // or Foundation

extension String {

func replace(target: String, withString: String) -> String {
return self.replacingOccurrences(of: target, with: withString)
}
}

Usage:

let newString = "the old bike".replace(target: "old", withString: "new")
print(newString) // "the new bike"

Here are some more common String extensions.

Example 3 - UIColor

UIColor+CustomColor.swift

import UIKit

extension UIColor {

class var customGreen: UIColor {
let darkGreen = 0x008110
return UIColor.rgb(fromHex: darkGreen)
}

class func rgb(fromHex: Int) -> UIColor {

let red = CGFloat((fromHex & 0xFF0000) >> 16) / 0xFF
let green = CGFloat((fromHex & 0x00FF00) >> 8) / 0xFF
let blue = CGFloat(fromHex & 0x0000FF) / 0xFF
let alpha = CGFloat(1.0)

return UIColor(red: red, green: green, blue: blue, alpha: alpha)
}
}

See here also.

Usage:

view.backgroundColor = UIColor.customGreen

Sample Image

Notes

  • Once you define an extension it can be used anywhere in your app just like the built in class functions.
  • If you are not sure of exactly what the function or property syntax should look like, you can Option+click a similar built in method. For example, when I Option+clicked UIColor.greenColor I see the declaration is class func greenColor() -> UIColor. That gives me a good clue for how to set up my custom method.
  • Apple Documentation for Extensions
  • In Objective-C extensions are known as categories.

Swift extension with extension

If you're using Swift 4+ :

protocol CanShowView {
func someFunction()
}

extension CanShowView where Self: UIViewController & SomeDelegate {
func someFunction() {
someView.SomeDelegate = self
}
}

If Swift 3.0:

protocol CanShowView {
func someFunction()
}

extension CanShowView where Self: UIViewController, Self: SomeDelegate {
func someFunction() {
someView.SomeDelegate = self
}
}

This is the right way to add conditional extensions, not in protocol definition. If you want to limit protocol to some constraint, best way to go is using associatedTypes.

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

What is the scope of extensions in swift?

The scope of an extension follows the same rules as when creating structs, classes and other types and variables in swift.

By default the extension is internal to the module it is created in and so accessible to all files in that module.

You can change that to public or private if you wish to.

The collisions you reference would occur if two extensions of the same were visible to each other and added a function with the same signature.

So, if you wanted to create your trimmed() extension in several files and give it a different implementation in each file you would need to make them all private to avoid any conflict.

Although… that might not be a good idea as it could be quite confusing with several of these in your project.

Creating a swift extension function for all controllers to access

If I have understood your desire correctly, you can achieve this with a manager class instead of extension, which will be responsible for downloading image for you. Create a class like below:

class ImageDownloaderManager {
class func loadImageFromDatabase(userImage: UIImageView, imageUrl: String, completionHandler: @escaping (Bool)-> Void) {

image.sd_setImage(with: URL(string: imageUrl!)) { (image, error, cache, urls) in
if (error != nil) {
userImage.image = UIImage(named: "1") // set your placeholder image maybe.
completionHandler(false)
} else {
userImageimage = image
completionHandler(true)
}
}
completionHandler(true)
}
}

It has a completion block where you can understand if your image was downloaded successfully or not from where-ever you call this function. Lets say you call this method from a viewController's viewDidLoad method as following:

override func viewDidLoad() {
super.viewDidLoad()
ImageDownloaderManager.loadImageFromDatabase(image: yourImage, imageUrl: yourImageURL) { (isSucceeded) in
if isSucceeded {
// It was successful, you could download the image successfully, do smth
} else {
// It was not successful image couldnt be downloaded, placeholder image has been set.
}
}
}

Swift: Extension on [SomeTypeT?] to produce [T?] possible?

I don't know if there is a simpler solution now, but you can use the same “trick” as in How can I write a function that will unwrap a generic property in swift assuming it is an optional type? and Creating an extension to filter nils from an Array in Swift, the idea goes back to this Apple Forum Thread.

First define a protocol to which all optionals conform:

protocol OptionalType {
associatedtype Wrapped
var asOptional: Wrapped? { get }
}

extension Optional : OptionalType {
var asOptional: Wrapped? {
return self
}
}

Now the desired extension can be defined as

extension Collection where Element: OptionalType, Element.Wrapped: SomeTypeProtocol {
var values: [Element.Wrapped.NumberType?] {
return self.map( { $0.asOptional?.value })
}
}

and that works as expected:

let arr = [SomeType(value: 123), nil, SomeType(value: 456)]
let v = arr.values

print(v) // [Optional(123), Optional(456)]
print(type(of: v)) // Array<Optional<Int>>

Should I keep extensions in their own Extensions file?

I think this is largely a matter of style rather than efficiency. That said, yes you should put them in their own file. That way if you want to reuse them between projects, you can simply drag and drop them into a new project.

In general, it is best to keep your files as small and modular as possible in order to keep things simple. If a piece of functionality doesn't specifically pertain to that file or viewcontroller then I think you should break it into its own file.

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.

How does protocol extension work in Swift?

I don't think there is even a need to inherit from NSObject if you are making a BaseClass to be inherited by other classes.

You can simply add classTag in the BaseClass itself, i.e.

class BaseClass {
var classTag: String {
return String(describing: type(of: self))
}
}

class SubClass: BaseClass {
func someFunc() {
print(self.classTag)
}
}

Another option can be to use protocol and protocol extension and provide the default definition of classTag, i.e.

protocol SomeProtocol {
var classTag: String { get }
}

extension SomeProtocol {
var classTag: String {
return String(describing: type(of: self))
}
}

Then, you can conform SomeProtocol to the classes wherever required, i.e.

class SubClass: SomeProtocol {
func someFunc() {
print(self.classTag)
}
}

In any case, inheriting from NSObject is unnecessary since you don't need any NSObject specific functionality for that.



Related Topics



Leave a reply



Submit