Swift convenience library for iOS 📱
Everything is better with a little coffee ☕️
The easiest way to get started is by installing via Xcode. Just add Espresso as a Swift package & choose the modules you want.
If you're adding Espresso as a dependency of your own Swift package, just add a package entry to your dependencies.
.package(
name: "Espresso",
url: "https://github.com/mitchtreece/Espresso",
.upToNextMajor(from: .init(3, 0, 0))
)
Espresso is broken down into several modules making it quick & easy to pick and choose exactly what you need.
Espresso
: Core classes, extensions, & dependenciesEspressoUI
: UIKit & SwiftUI classes, extension, & dependenciesEspressoPromise
: PromiseKit classes, extensions, & dependencies
As of Espresso 3.1.0
, CocoaPods support has been dropped in favor of SPM. If you're depending on an Espresso version prior to 3.1.0
, you can still integrate using CocoaPods.
pod 'Espresso', '~> 3.1.0'
Espresso adds a bunch of useful features and extensions to components commonly used while developing for Apple platforms.
Some of the more interesting things include:
UIAnimation
classes with a promise-like chaining systemUIViewControllerTransition
system for easy customUIViewController
transitionsAppleDevice
identification & informationMVVM
base classes (i.e.ViewModel
,UIViewModelView
,UIViewModelViewController
)Combine
helper classes & extensions- Crypto & digest hashing helpers
- User authentication (Face ID, Touch ID, Passcode) helpers
- + much more!
Espresso includes a robust animation system built on top of UIViewPropertyAnimator
. An animation is created with a timing curve, duration, delay, & animation closure.
let view = UIView()
view.alpha = 0
// Simple curve (default timing + default values)
UIAnimation {
view.alpha = 1
}.start()
// Simple curve (default timing + custom values)
UIAnimation(duration: 0.5, delay: 0) {
view.alpha = 1
}.start()
// Simple curve (custom)
UIAnimation(.simple(.easeOut), duration: 0.4) {
view.alpha = 1
}.start()
// Spring curve
UIAnimation(.spring(damping: 0.9, velocity: 0.25)) {
view.alpha = 1
}.start {
print("The animation is done!")
}
The following timing curves are currently supported:
simple
cubicBezier
spring
defaultSpring
material
custom
UIAnimation
also supports animation chaining. This let's you easily define a series of animations to run in succession (similar to a key-frame animation) using a promise-like syntax.
UIAnimation(duration: 0.3) {
view.alpha = 1
}.then {
view.backgroundColor = .red
}.start()
All parameters of a regular UIAnimation
are available to you while chaining:
UIAnimation(duration: 0.3) {
view.alpha = 1
}.then(.defaultSpring, duration: 0.4) {
view.backgroundColor = UIColor.red
}.start()
Animations can be created and executed at a later time! Running your animations directly from an array without chaining is also supported.
let a1 = UIAnimation {
view.alpha = 1
}
let a2 = UIAnimation(.simple(.easeIn), duration: 0.5) {
view.backgroundColor = UIColor.red
}
[a1, a2].start {
print("The animations are done!")
}
Built on top of UIAnimation
, Espresso's view controller transition system makes it easy to build beautiful custom transitions into your app. A simple UIViewControllerTransition
implementation might look something like this:
class CustomFadeTransition: UIViewControllerTransition {
public override func animations(using ctx: Context) -> UIAnimationGroupController {
let sourceVC = ctx.sourceViewController
let destinationVC = ctx.destinationViewController
let container = ctx.containerView
let context = ctx.context
return UIAnimationGroupController(setup: {
destinationVC.view.alpha = 0
destinationVC.view.frame = context.finalFrame(for: destinationVC)
container.addSubview(destinationVC.view)
}, animations: {
UIAnimation {
destinationVC.view.alpha = 1
}
}, completion: {
context.completeTransition(!context.transitionWasCancelled)
})
}
}
There's only one function that needs to be overridden from a transition subclass, animations(using:)
. This function provides you with contextual information about the transition, and expects you to return a UIAnimationGroupController
containing setup, animation, & completion closures.
To present your view controller using a transition, set it's transition
property before presentation. Helper functions on UIViewController
& UINavigationController
have also been added:
let transition = CustomFadeTransition()
present(
viewController,
using: transition
)
navigationController.push(
viewController,
using: transition
)
The following view controller transitions are included with Espresso:
UIFadeTransition
UISlideTransition
UICoverTransition
UIRevealTransition
UISwapTransition
UIPushBackTransition
UIZoomTransition
The UserAuthenticator
class helps with authenticating a user via Face ID, Touch ID, or a passcode. An appropriate authentication type will be chosen automatically (i.e. devices that support Face ID will prefer Face ID, devices with Touch ID will use Touch ID). If Face ID & Touch ID are unavailable, passcode authentication will be used.
UserAuthenticator.authenticate(withReason: "The app needs to authenticate you.") { (success, error) in
print("Authenticated: \(success)")
}
NOTE: NSFaceIDUsageDescription
key must be added to your Info.plist if you intend to authenticate via Face ID.
Hashing extensions are available on both Data
& String
:
let data = Data()
let hashedData = data.hashed(using: .md5)
let string = "Hello, world!"
let hashedString = string.hashed(using: .md5)
The following hash types are included with Espresso:
md5
sha1
sha224
sha256
sha384
sha512
Pull-requests are more than welcome. Bug fix? Feature? Open a PR and we'll get it merged in! 🎉