extensions-kit 1.8.0

extensions-kit 1.8.0

Maintained by Astemir Eleev.



  • By
  • Astemir Eleev

extensions-kit Awesome

Platforms Language CocoaPod Build Status Coverage License

Last Update: 18/May/2019.

If you like the project, please give it a star ⭐ It will show the creator your appreciation and help others to discover the repo.

✍️ About

📦 Collection of Swift extensions(+ custom types) for various use cases. The kit contains 200 extensions + 24 custom types.

🏗 Installation

CocoaPods

extensions-kit is availabe via CocoaPods

pod 'extensions-kit', '~> 1.8.0' 

Manual

You can always use copy-paste the sources method 😄. Or you can compile the framework and include it with your project.

✏️ Notes

Please read these notes before openning any new issues or "burning" this repo 🔥😅:

  • Technically you may reuse the majority of the extensions for macOS, watchOS and tvOS, even without the direct support of those OSs
  • Please, note that this framework was developed for proprietary projects, later on it was decided to open source it. It's far from being finished, however it does provide some value. Those parts that are unit-test covered were/are actually extensively used in real projects
  • Many of the presented extensions are experimental. They represent the state of mind at the moment of development. They may not reflect your own vision of doing things, or they may have some issues. Please, be polite and professional and describe your issues (if any) by openning a new issue, or searching for existing one
  • The best way to help is to contribute by implementing fixes/features or additions and openning pool requests

🗺 Roadmap

  • Add TravisCI support
  • Add Codecov support
  • Remove non iOS extensions (AppKit)
  • Add support for docs generation
  • Add unit test coverage and keep it at a high level
  • Cover the framework with docs and sample code

🍱 Categories

List of categories for convenient navigation. The numbers represent total number of extensions for a given category + custom types. Each extension file may contain a number of extensions, grouped by a category.

📚 List of Extensions

All the extensions are split into separete groups each of which represents a separete SDK framework.

AppKit

NSBezierPath

NSBezierPath+cgPath

Adds missing cgPath property that converts self (port of similar functionality from iOS)

let path = bezierPath.cgPath
// path is of type CGPath and can be used in a shared code with iOS, tvOS or watchOS targets

AVFoundation

AVCaptureDevice+ToggleFlash

Adds support for easy flashlight management:

AVCaptureDevice.toggleFlashlight(with: .max)

Core Animation

CAAnimation

CAAnimation+PatternReplicator

Creates a pattern-based, wavy animation for the specified image, layer size and other properties:

CAAnimation.patternReplocator(with: UIImage("image"), size: CGSize(width: 600, height: 600), targetLayer: drawerView.layer)

Core Graphics

CGSize

CGSize+Operators

Various mathematical operators such as +, -, *, / for convenience:

CGSize(width: 10, height: 20) + CGSize(width: 25.4, height: 23.6)
CGSize(width: 10, height: 20) - CGSize(width: 25.4, height: 23.6)
CGSize(width: 10, height: 20) * CGSize(width: 25.4, height: 23.6)
CGSize(width: 10, height: 20) / CGSize(width: 25.4, height: 23.6)

CGPoint

CGPoint+Operators

Various mathematical operators such as +, -, *, /, lerp etc.:

var origin: CGPoint = .zero
let addPoint = origin + CGPoint(x: 10, y: 3)
origin += CGPoint(x: 12, y: 5)
let subPoint = origin - CGPoint(x: 12, y: 5)
        
let interpolatedPoint = CGPoint.lerp(start: pointOne, end: pointTwo, t: 2)

CGPoint+Utils

Missing mathematical utilities such as normalized, lenght, distanceTo and angle:

let point = CGPoint(x: 3, y: 5)
let _ = point.length()
let _ = point.angle
let _ = point.normalized()
let distanceBetweenTwoPoints = point.distanceTo(anotherPoint)
let _ = point.lengthSquared()

CGRect

CGRect+Scale

Scales self to the specified size:

let rect = CGRect(origin: .zero, size: CGSize(width: 100, height:
            200))
let newSize = rect.scaled(to: targetSize)

CGRect+Corners

Adds properties for topLeft, topRight, bottomLeft and bottomRight points:

let rect = CGRect(origin: .zero, size: CGSize(width: 100, height:
            200))
rect.topLeft
rect.topRight
rect.bottomLeft
rect.bottomRight

CGRect+Mid

Adds property for mid point of self:

let rect = CGRect(origin: .zero, size: CGSize(width: 100, height:
            200))
rect.mid

CGRect+AspectFit

Adds aspectFit(inRect: CGRect) -> CGRect method that scales self to fit the specified CGRect:

let rect = CGRect(origin: .zero, size: CGSize(width: 100, height:
            200))
rect.aspectFit(inRect: targetRect)

CGFloat

CGFloat+Rounded

Rounds self to the specified decimal places:

let val: CGFloat = 4.32
let roundedVal = val.rounded(toPlaces: 1) // roundedVal holds `4.3`

CoreImage

New Filters

HighlightFilter

Filter is originally designed for highlighting 3D objects but can be used to add this effect to images and sprites.

CIImage

CIImage+Inverted

Inverts the colors of self:

let invertedImage = ciImage.inverted
// invertedImage holds the same image data but with inverted colors

CIImage+QRImage

Generates a QR image from the input text and with an optional scale parameter that specifies the affine transformation for the output CIImage:

let helloWorldQRImage = CIImage.qrImage(from: "Hello World!")
// helloWorldQRImage holds image data that represents QR code for `Hello World!` message

CIImage+Tinted

Applies the specified color as a tint color:

let redQRImage = qrImage.tinted(by: .red)
// redQRImage holds the same QR image data as before but tinted by red color

CIImage+Transparent

A number of extensions that convert the target CIImage instance to it's transparent version by applying alpha masking filter:

let transparentImage = ciImage.transparent
let blackTransparentImage = anotherImage.blackTransparent

Foundation

NSObjectProtocol

NSObjectProtocol+KVO+KVC

Observe and bind observables with ease:

// Binding is as easy as writing just a single line of code:
viewModel.bind(\.progressSlider, to: progressSlider, at: \.value)

// Observing for changes is thinner than the `Swifts 4.0` updated `KVO`:
viewModel.observe(\.buttonTitle) { [button] in
        button!.setTitle($0, for: .normal)
}

Custom Protocols

Identifiable

The protocol supposed to be used with types that need identification, such as UITableViewCell, UITableViewHeaderFooterView, UICollectionReusableView etc.:

class FeedTableViewCell: UITableViewCell, Identifiable {
       // ... 
       // Implementation details
       // ... 
}

// Somewhere in `UITableViewControllerDelegate`:
let cell = dequeueReusableCell(withIdetifier: cell. reuseIdentifier)

Then

Protocol for object configuration:

var imageView = UIImageView().then {
        $0.layer.cornerRadius = 10
        $0.contentMode = .scaleAspectFill
        $0.clipsToBounds = true
}

Custom Types

Variable

Lightweight bindable data type that allows to get on update notifications for a given value. Can be used with MVVM or any another architectural pattern to replace the need for 3rd party, heavyweight binding framework:

let stringVariable = Variable("Initial Value")
let newValue = "New Value"
stringVariable.value = newValue

stringVariable.onUpdate = {
        let isEqual = $0 == newValue
        XCTAssert(isEqual)
}

Debouncer

Allows an action to be performed after a delay:

let debouncer = Debouncer(delay: 2.0)
debouncer.schedule {
        value = "Changed Value"            
}
// After 2.0 seconds the value will be changed to "Changed Value"

ObservableArray

Syncronous, thread-safe observable array type:

let array: ObservableArray = [1,2,3,4,5]
array += 6
array += [7,8]

array.allChanges = { change in
        // Both changes will, for addition of `6` and `[7,8]` will be reflected in `change` property and the appropriate callbacks will be made
}

array.removeFirst()
array.removeLast()
array.remove(at: 4)

Custom TextOutputStream

FileOutputStream

Prints the output stream to the specified file for the given URL and encoding:

let url = URL(fileURLWithPath: "/somePath/subpath/file.rtf")
let fileHandle = try FileHandle(forWritingTo: url)
var textOutputStream = TextOutputStream(fileHandle)

print("\(outputString)", &textOutputStream)
// The print statement will write the output stream to the specified FileHandle at the specified URL. This stream mimics Java's SDK File Output Stream. 

Prints all the Unicode characters with the following scheme:

var unicodeOutputStream = UnicodeOutputStream()
print("👨‍👩‍👧‍👧", to: &unicodeOutputStream)

// Will print all the unicode indices + characters + names

Functions

FunctionalComposition

Is a number of functions that implement Functional Composition concept which allows to combine multiple functions and chain them together, in order to transform data. Consider the following construction: (doubleNumbers ->> squareNumbers ->> convertToStringArray)(array) which returns a processed array by linearly composing the functions (rather that nesting the function calls). Also the extension includes the reversed operator that composes functions in reversed order:

func double<T: Numeric>(array: [T]) -> [T] {
        return array.map { $0 * 2 }
}
        
func square<T: Numeric>(array: [T]) -> [T] {
        return array.map { $0 * $0 }
}
        
func toStringArray<T: Numeric>(array: [T]) -> [String] {
        return array.map { "\($0)" }
}

let data = [1,2,3,4,5]
let newData = (double ->> square ->> toStringArray)(data)        
// newData now equals to ["4", "16", "36", "64", "100"]

Data Structures

BuilderProtocol

Allows AnyObject to be extended with chainable initialization methods by using Keypath feature. Please note that the extension works only since Swift 4.0:

// 1. Add conformance to BuilderProtocol
extension Song: BuilderProtocol { /* empty implementation */ }

// 2. Then you can use Key-Path builder approach:
let song = Song()
        .init(\.author,         with: author)
        .init(\.name,           with: name)
        .init(\.genre,          with: genre)
        .init(\.duration,       with: duration)
        .init(\.releaseDate,    with: releaseDate)

Lens

Lens is an implementation of Functional Lenses concept that allows to safely modify immutable structs and provides fundamental tools to work with complex data structures (see UnitTests):

extension Actor {
    struct Lenses {
        static let name = Lens<Actor, String>(
            get: {$0.name},
            set: {(me, value) in Actor(name: value, surname: me.surname) }
        )
        static let surname = Lens<Actor, String>(
            get: {$0.surname},
            set: {(me, value) in Actor(name: me.name, surname: value) }
        )
    }
}

extension Movie {
    struct Lenses {
        static let mainActor = Lens<Movie, Actor?>(get: { movie in
            let actor: Actor? = movie.actors.first
            return actor
        }, set: { me, actor -> Movie in
            guard let actor = actor else { return me }
            
            return Movie(name: me.name, year: me.year, actors: [actor] + me.actors)
        })
    }
}

ObjectPool

Thread-safe implementation of ObjectPool design pattern:

let objectPool = ObjectPool(objects: [resource, anotherResource, thirdResource])
let reusedResource = objectPool.dequeue()
objectPool.enqueue(object: reusedResource)
objectPool.eraseAll()

Observer

Thread-safe implementation of Observer design pattern (don't confuse with NotiifcationCenter - it's an implementation of Publish-Subscribe pattern):

let observerOne = ObserverOne()
var observerTwo: ObserverTwo? = ObserverTwo()
let observerThree = ObserverThree()

let subject = Subject()
subject += [observerOne, observerTwo!, observerThree]

subject ~> EmailNotification(message: "Hello Observers, this messag was sent from the Subject!")

// Will produce the following output:
// 
// Observer One:  data: Optional("Hello Observers, this messag was sent from the Subject!")
// Observer Two:  data: Optional("Hello Observers, this messag was sent from the Subject!")
// Observer Three:  data: Optional("Hello Observers, this messag was sent from the Subject!")

MulticastDelegation

Non thread-safe implementation of MulticastDelegation design pattern:

// Create the view controllers that will be delegates
let containerViewController = ContainerViewController()
let profileViewController = ProfileViewController()

let profileModel = ProfileModel()

// Attach the delegates
profileModel.delegates.add(delegate: containerViewController)
profileModel.delegates.add(delegate: profileViewController)

// Change the model
profileModel.name = "John"

// After changing `name` property we got the following in console:
// ContainerViewControllers:  didUpdate(name:)  value:  John
// ProfileViewController:  didUpdate(name:)  value:  John

// Assume that we needed to remove one of the delegates:
profileModel.delegates.remove(delegate: profileViewController)

// And again update the model:
profileModel.city = "New York"
// This time the console outputs is the following:
// ContainerViewControllers:  didUpdate(city:)  value:  New York

// We again attach ProfileViewController
profileModel.delegates.add(delegate: profileViewController)

// Custom closure that is called outside of the model layer, for cases when something custom is required without the need to touch the original code-base. For instance we may implement this function in our view-model layer when using MVVM architecture
profileModel.delegates.update { modelDelegate in
    modelDelegate.didSave()
}

Stack

Is an implementation of Stack data structure:

var stack: Stack = [1,2,3,4,5,6,7,8,1]
let lastElement = stack.pop()
stack.push(element: 10)

Queue

Is an implementation of Queue data structure:

var queue: Queue = [1,2,3,4,5,6,7,8,1]
queue.enqueue(element: 9)
let dequeuedElement = queue.dequeue()

ProrityQueue

Is an implementation of Prority Queue data structure based on Heap data structure:

var queue = PriorityQueue<Int>(elements: [2, 1, 4, 3, 5], order: >)
queue.enqueue(9)

Dequeue

Is an implementation of Dequeue data structure:

var dequeue = Dequeue([1,2,34,5,6,7])
let back = dequeue.dequeueBack()
let front = dequeue.dequeueFront()

dequeue.enqueue(front: 99)
dequeue.enqueue(back: 99)

LinkedList

Is an implementation of Linked List data structure:

var list: LinkedList = [1,2,4,5]
list.pop()

var newList = LinkedList<Int>(sequence: list)
newList.pop()

DoublyLinkedList

Is an implementation of Doubly Linked List data structure:

var list: DoublyLinkedList = [1,2,4,5,6,7]
list.head
list.tail

list.removeHead()
list.removeTail()

list.push(newHead: 99)
list.push(newTail: 101)

Heap

Is an implementation of Heap data structure:

var maxHeap = Heap<Int>(order: >)
maxHeap.insert(node: 1)
maxHeap.insert(node: 5)
maxHeap.insert(node: 2)
maxHeap.insert(node: 7)
maxHeap.insert(node: 9)

maxHeap.index(of: 3)
let sortedHeapmaxHeap.sorted()

Extensions

Array

Array+Filtering

Contains a number of methods for filtering in a functional-style, has skip, all and any filters

let result = [1,2,3,4,5,6,7,8,9,10].skip(5)
// result array contains all the elements except the first 5 e.g. [6,7,8,9,10]

let result = [1,2,3,4,5,6,7,8,9,10].all { $0 < 20 }
// result will be true since all the elements are less than 20

let result = [1,2,3,4,5,6,7,8,9,10].any { $0 < 5 }
// result will be true since there are a number of elements that are less than 5

Array+Contains

Checks if self contains the specified elements

let result = [1,2,4,5,6,7,8,9,10].contains(elements: 1,2,4,5)
// result will be true since the target array contains all the specified elements

let result = [1,2,4,5,6,7,8,9,10].contains(elements: 9,10,11,12)
// result will be false since the target array does not contain 11 and 12

Array+Difference

Computes differences between self and the input arrays

let testA = [1,2,3,4,5]
let testB = [4,5,7,8,9]

let result = testA.difference(elements: testB)
// result will be [1,2,3]

let result = testB.difference(elements: testA)
// result will be [7,8,9]

Array+Intersection

Computes intersection of self and the input values

let testA = [1,2,3,4,5]
let testB = [4,5,6,7]

let result = testA.intersection(values: testB)
// result will be [4,5]

Array+Union

Unions self and the input arrays

let result = [1,2,4,5,6,7,8].union(value: [8,9,10])
// result will be [1, 2, 4, 5, 6, 7, 8, 9, 10]

Array+Remove

A set of methods that remove Element form an array by mutating it

var test = [1,2,3,4,5,6,7,8]

test.remove(object: 8)
// test contains the following elements [1,2,3,4,5,6,7]

test.remove(objects: [1,2,4])
// test contains the following elements [3,5,6,7]

test.remove(objects: 5,6)
// test contains the following elements [3,7]

Array+InsertionSort

Adds support for Insertion Sort algorithm

Array+MergeSort

Adds support for Merget Sort algorithm

Array+QuickSortHoareScheme

Adds support for Quick Sort algorithms using Hoare's partitioning scheme

Array+QuickSortLomutoScheme

Adds support for Quick Sort algorithm using Lomuto's partitioning scheme

Array+BubbleSort

Adds support for Bubble Sort algorithm

Array+ShellSort

Adds support for Shell Sort algorithm

Array+RadixSort

Adds support for Radix Sort algoritm

Bool

Bool+Int

Adds a property that returns Int representation of self

Bool+Random

Adds a random property for self

ClosedRange

ClosedRange+Random

Adds a property that generates a random Int with respect to self

Collection

Collection+ParallelIteration

Adds parallelForEach method

Collection+RandomItem

Adds a property that returns a random element from self

Collection+Sum&Average

Adds two properties for sum and average with the corresponding functionality

Collection+SafeSubscript

Safely checks whether the collection is able to retreive an element for the given Index, otherwise it will return nil

RandomAccessCollection

RandomAccessCollection+BinarySearch

Implementation of Binary Search algorithm

Decodable

Decodable+DecodeFromFile

Decodes a file into a type:

// User is a .json file containing the following data:
// {
//    "name":"Willy",
//    "age":30
// }

let decodedUser = try? User.decodeFromFile(named: "User")
// decodedUser will be a Decodable struct named User with two properties for name and age

Dictionary

Dictionary+GetOrAddValue

Parses self as JSON to Data or String

Dictionary+JSON

Checks for a value for a given key or creates a new key/value pair if none was found

Dictionary+ConvenienceWrappers

Adds wrappers around common operations such as has(key: )->Bool and each(: (Key, Value)->())

Dictionary+Difference

Computes differences between self and the input dictionaries

Dictionary+Intersection

Computes intersection of self and the input Dictionaries

Dictionary+Map

Custom mapping function

Dictionary+Union

Unions self and the input dictionaries

Double

Double+Rounded

Rounds self to decimal places value

Double+CurrencyShorcuts

Adds several commonly used currency shortcuts as properties

Date

Date+FirstLast

Adds a number of properties that allow to quickly access: first day of a week, start of a day, end of a day and a number of days in a month

Date+PreviousNext

Adds properties that allow to get access to the previous and next days

Float

Float+Rounded

Rounds self to decimal places value

Int

Int+Clamp

Clamps self into a range that can be described using ClosedRange or two separate properties

Int+Digits

Adds digitCount property that contains the number of digits for self

Int+EvenOdd

Checks whether self is even or if it's odd

Int+Factorial

Computes factorial of self

Int+Power

Operator that performs exponentiation matematical operation, where left number is the base and the right one is the exponent

Int+Random

Generates pseudo-random number in a range that can be specified as ClosedRange or two separate Int properties

Int+Roman

Converts self into Roman number (as String)

Int+DecimalToBinary

Allows to convert decimal number to binary format and vice versa

OptionSet

OptionSet+Operations

Adds support for in-place insert and remove operations

MutableCollection

MutableCollection+Shuffle In-place shuffling of self

Sequence

Sequence+Shuffle

Shuffles the elements of self

Sequence+Count

Counts the number of occurrences of a logical expression

Sequence+DuplicatesRemoved

Removes the duplicate elements and returns the new Sequence without duplicates if any

String

String+Subscript

Adds conformances to CoutableClosedRange, CountableRange, PartialRangeThrough and PartialRangeFrom protocols support in a form of subscripts

String+Digits

Combines decimal digits into a single String property

String+FormattedDate

Creates a Date instance from self based in the specified format

String+IndexOf

Finds the first occurence for a given String

String+Base64

Encodes/decodes self to Base64 encoding

String+Validation

Contains a number of extensions for validating String based on the following: isAlphanumeric, hasLetters, hasNumbers, isEmail, isAlphabetic

NSObject

NSObject+ClassName

Allows to get the exact class name:

let className = Foo.nameOfclass
// className property holds `Foo`

NotificationCenter

NotificationCenter+PostUtils

Various utility extensions that help to reduce the boilerplate code:

NotificationCenter.post(notification: .userHasUpdated)

OperationQueue

OperationQueue+MainUtils

Utility extensions for .main operation queue:

OperationQueue.isMain // if current operation queue is the main the result will be true, otherwise false
OperationQueue.onMain {
        // This closure will be executed on the main operation queue
}

URL

URL+QRImage

Creates a QR image from the absoluteString of the URL:

let customUrlQRImage = url.qrImage()
// customUrlQRImage holds image data for QR image that represents the given URL address

UIKit

Badge

Badge

A custom type, wrapper badge app icon API that simplifies development

UIScreen

UIScreen+InterfaceOrientation

Interace orientation for the current UIScreen

UIApplication

UIApplication+SafeAreas

Contains extensions that allow to get numerical representations of top and bottom safe areas

NSLayoutConstraint

NSLayoutConstraint+Animation

Allows a constraint to be animated when animated flag is a set to true (default is false)

NSLayoutConstraint+Activation

Adds convenience methods for setting and activating layout priorities

UIView

UIView+CACorners

Convenience extension for setting and getting round corners

UIView+BezierRoundedCorners

Yet another extension for rounding corners

UIView+HuggingPriority

Convenience wrappers that simplify inerfaces for setContentHuggingPriority and setContentCompressionResistancePriority methods

UIView+Screenshot

Allows to take a screenshot of self

UIView+Constraints

Adds convenience auto-layout methods that allow to pin, add, get height & width and to get all the constrains for a particular UIView

UIView+LayoutAnimation

Adds animation extensions that operate on layout constraints

UIView+Masking

Masks the view with the specified UIRectCorner array and corner radius:

let view = UIView()
view.mask(corners: .allCorners, with: 10)

UIColor

UIColor+ColorComponents

Adds support for missing color components properties such as rgba, hsba and grayscale

UIColor+Blend

Blends two colors by mixing the RGBA components:

let blendedColor = red.blend(with: blue, intensity: 0.5)

UIColor+Brightness

Changes the brightness of a color:

let brighterRed = red.increaseBrightness(0.25)

UICollectionView

UICollectionView+CustomCellRegistration

Registers custom UICollectionViewCell for a UICollectionView instance. UICollectionViewCell needs to be located in current Bundle

UICollectionView+ScrollingUtils

Adds methods that allow to programmatically scroll to the top, bottom or to the specified index path of a table view

UICollectionView+Safety

Adds validation utils

UICollectionView+Operations

Convenience reload, delete and insert operations for collections of item indices

UITableView

UITableView+FooterHeaderUtils

The extension adds convenience helpers for working with Footer and Header views

UITableView+ScrollingUtils

Adds methods that allow to programmatically scroll to the top, bottom or to the specified index path of a table view

UITableView+Safety

Adds validation utils

UIImage

UIImage+Downsample

Downsamples the input image to the specified point size and scale factor. Can be used to present the thumbnails, supports caching:

let downsampledImage = UIImage.downsample(imageAt: url, to: targetSize)
// downsampledImage stores a `UIImage` instance that was cached and downsized to the `targetSize`

UIImage+ImageFromUIView

Renders UIView to UIImage

UIImage+LandscapeCameraOrientationFix

Fixes image orientation for cases when the image was captured using AVFoundation in landscape interface orientation

UIImage+RawOrientation

Raw image orientation (from UIImageOrientation to Int32)

UIImage+Resize

Class-level extension that allows to resize input image based on expected image width or/and height

UIImage+SolidColor

Create a UIImage from the color data and size

UIImage+Inverted

Adds a property that returns an inverted copy of self

UIImageView

UIAlertController

UIAlertController+Presentation

Presents a UIAlertController with the given title, message, tintColor and alert actions:

UIAlertController.present(with: "Warning!", and: "The item will be deleted", from: targetViewController) { () -> [UIAlertAction] in
        let deleteAction = UIAlertAction(title: "Delete",
                                         style: .destructive,
                                         handler: { (action) in
                // Callback handling
        })
            
        let cancelAction = UIAlertAction(title: "Cancel",
                                         style: .cancel,
                                         handler: { (action) in
                // Callback handling
        })
            
        return [deleteAction, cancelAction]
}

UIViewController

UIViewController+ContainerController

Loads, adds and removes container view controllers as children

UIViewController+ChildViewControllers

Addds convenience methods for adding and removing child view controllers

UIViewController+Storyboard

Instantiates a UIViewController instance from a Storyboard using the UIViewController's name as a reference name of the Storyboard file. Used in cases when Coordinator or Flow design patterns need to be implemented

// Instantiation of a view controller by explicitly setting the storyboard and identifier
let loginViewController = UIViewController.instantiateController(from: mainStoryboard, identifier: "LoginViewController")

// An another way to instantiate a UIViewController instnace: here the identifier will be the class name
let viewController = UIViewController.instantiateController(from: mainStoryboard)

UIWindow

UIWindow+Instantiate

Syntactic sugar for much easier UIWindow instantiation:

window = UIWindow.create(with: coordinator.rootViewController, option: .keyAndVisible)

os

OSLog

OSLog+LogLevels

Adds a number of convenient log levels and a global function that simplifies logging:

os_log("Received .json data from the remove", log: .network)
os_log("Attempting to sync with the main UI thread", log: .ui)

SpriteKit

SKTimingFunction

Adds 36(!) different timing functions

SKEmitterNode

SKEmitterNode+AdvanceSimulation

Safely advance the particle simulation for a given TimeInterval

SKSpriteNode

SKSpriteNode+GIF

Adds support for uploading and playing GIFs from local files

SKScene

SKScene+SerialSpriteLoading

Uploads a set of scene graph nodes with a specific pattern, useful when a scene contains a lot of nodes, but just a specific subset needs to be processed or accessed

SKScene+ReferenceNodeFix

A small fix that resolves the default behavior for nodes that were referenced from differnet .sks files. The thing is that they do not launch their animations by default, so this small hack fixes this issue

SKTexture

SKTexture+LinearGradient

Adds a convenience initializer that generates a gradient texture for the specified size, start and end colors

SKTextureAtlas

SKTextureAtlas+FramesLoader

Uploads an animation sequence from a texture atlas and returns an array of textures that can be futher used

SceneKit

SCNVector3+Operators

Adds support for various mathematical operators for SCNVector3 type

SCNAction+MoveAlong

The extension adds a new action method that allows a node to move along a UIBezierPath:

let flyoverAction = SCNAction.moveAlong(path: flyoverPath, z: 10, speed: plane.speed)
plane.run(flyoverAction)

WebKit

WKWebView

WKWebView+Load

Adds support for navigating to the requested URL using String

PhotoKit

PHAsset

PHAsset+URL

Provides possibility to get URL for image and video media types

🙋‍♀🙋‍♂️Contributing

  • There is just one main rule for contributors - please include your extensions in separete files. It's important since such extension can be more easily referenced and reused.
  • The other soft rule is - please include unit tests with your extensions.

👨‍💻 Author

Astemir Eleev

🔖 Licence

The project is available under MIT licence