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
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
✏️ 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
andtvOS
, even without the direct support of thoseOSs
- 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.
- AppKit - 1
- AVFoundation - 1
- Core Animation - 1
- Core Graphics - 16
- Core Image - 6
- Foundation - 109
- UIKit - 65
- os - 1
- SpriteKit - 11
- SceneKit - 2
- WebKit - 1
- PhotoKit - 1
- concurrency-kit - for
GCD
extensions + even more
📚 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
- UIImageView+DownloadFromURL - adds a convenience method for downloading and parsing
UIImage
with the specifiedURL
- UIImageView+Masking - masks a given
UIImage
with the target image size
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 includeunit tests
with your extensions.
👨💻 Author
🔖 Licence
The project is available under MIT licence