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.
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
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 isclass 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 associatedType
s.
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
Why Is an Observedobject Array Not Updated in My Swiftui Application
Difference Between 'Let' and 'Var' in Swift
How to Resolve "Ambiguous Use Of" Compile Error With Swift #Selector Syntax
Uncaught Error/Exception Handling in Swift
Overriding Superclass Property With Different Type in Swift
Strange Swift Numbers Type Casting
How to Unwrap an Optional Value from Any Type
Checking If an Object Is a Given Type in Swift
Nsuserdefaults Not Working on Xcode Beta With Watch Os2
Call a Method from a String in Swift
What Does the Dollar Sign Do in Swift/Swiftui
How to Convert a Decimal Number to Binary in Swift
Constant Unassigned Optional Will Not Be Nil by Default
Noop For Swift'S Exhaustive Switch Statements