Espresso
Espresso is a Swift convenience library for iOS.
Everything is better with a little coffee.
Installation
CocoaPods
use_frameworks!
pod 'Espresso', '~> 3.0'
Subspecs
Espresso is broken down into several subspecs making it quick & easy to pick and choose what you need. By default, the UIKit subspec is installed.
Core: Core classes, extensions, & dependenciesUIPromiseKit: PromiseKit classes, extensions, & dependenciesUIKit: Aggregate subspec that includes everything related to UIKitSwiftUI: Aggregate subspec that includes everything related to SwiftUIAll: Aggregate subspec that includes everything
If you're unsure of what you want/need, we also some "recipe" subspecs that provide a good starting point with bundled Espresso classes & common third-party dependecies.
Recipe-Modern-UIKitEspresso/UI-UIKitEspresso/PromiseKit- Spider-Web
/All - Director/
All - Swinject
Espresso
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:
UIAnimationclasses with a promise-like chaining systemUIViewControllerTransitionsystem for easy customUIViewControllertransitionsAppleDeviceidentification & informationMVVMbase classes (i.e.ViewModel,UIViewModelView,UIViewModelViewController)Combinehelper classes & extensions- Crypto & digest hashing helpers
- User authentication (Face ID, Touch ID, Passcode) helpers
- + much more!
UIAnimation
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:
simplecubicBezierspringdefaultSpringmaterialcustom
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!")
}UIViewControllerTransition
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:
UIFadeTransitionUISlideTransitionUICoverTransitionUIRevealTransitionUISwapTransitionUIPushBackTransitionUIZoomTransition
User Authentication
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.
Digest Hashing
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:
md5sha1sha224sha256sha384sha512
Contributing
Pull-requests are more than welcome. Bug fix? Feature? Open a PR and we'll get it merged in!
