Skip to content

Instantly share code, notes, and snippets.

@simme
Created March 21, 2018 15:57
Show Gist options
  • Save simme/375409e41fb713b99cc3591b2b1ac8eb to your computer and use it in GitHub Desktop.
Save simme/375409e41fb713b99cc3591b2b1ac8eb to your computer and use it in GitHub Desktop.
//
// UIView+AutoLayout.swift
//
// Created by Simon Ljungberg on 28/12/16.
// Copyright © 2016 Redhill. All rights reserved.
//
import UIKit
public extension UIView {
/**
Disables auto-translation of resizing masks into constraints, preparing the reciever for Auto Layout.
- Returns: The receiver.
*/
@discardableResult
func forAutoLayout() -> Self {
translatesAutoresizingMaskIntoConstraints = false
return self
}
/**
Locks the frame of the reciever with the one of the provided view.
- Parameter view: The view to lock the reciever's frame with.
- Parameter padding: Optional padding applied to the frame. Positive values means the view is inset from
the reciever.
- Returns: The receiver.
*/
@discardableResult
func lockFrame(withView view: UIView, withPadding padding: UIEdgeInsets = .zero) -> Self {
NSLayoutConstraint.activate([
self.topAnchor.constraint(equalTo: view.topAnchor, constant: padding.top),
self.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -padding.bottom),
self.leftAnchor.constraint(equalTo: view.leftAnchor, constant: padding.left),
self.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -padding.right),
])
return self
}
@discardableResult
func setContent(of scrollView: UIScrollView) -> Self {
NSLayoutConstraint.activate([
scrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: self.heightAnchor),
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor),
])
return self
}
/**
Locks the center of the reciever with the one of the provided view.
- Parameter view: The view which center to lock the reciever's center to.
- Parameter offsetX: An optional value used to offset the reciever's horizontal center from the one of the
provided view.
- Parameter offsetX: An optional value used to offset the reciever's veritcal center from the one of the
provided view.
- Returns: The receiver.
*/
@discardableResult
func lockToCenter(ofView view: UIView, offsetX: CGFloat = 0, offsetY: CGFloat = 0) -> Self {
NSLayoutConstraint.activate([
self.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: offsetX),
self.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offsetY),
])
return self
}
/**
Lock the top of the reciever to the one of the provied view.
- Parameter view: The view which top to lock to the receiver's.
- Parameter padding: An optional padding to apply between the top of `view` and the reciever.
- Returns: The receiver.
*/
@discardableResult
func lockToTop(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
NSLayoutConstraint.activate([
self.topAnchor.constraint(equalTo: view.topAnchor, constant: padding),
])
return self
}
/**
Lock the bottom of the reciever to the one of the provied view.
- Parameter view: The view which bottom to lock to the receiver's.
- Parameter padding: An optional padding to apply between the bottom of `view` and the reciever.
- Returns: The receiver.
*/
@discardableResult
func lockToBottom(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
NSLayoutConstraint.activate([
self.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -padding),
])
return self
}
@discardableResult
func lockToLeft(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.leftAnchor.constraint(equalTo: view.leftAnchor, constant: padding).isActive = true
return self
}
@discardableResult
func lockToLeadingMargin(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding).isActive = true
return self
}
@discardableResult
func lockToTrailingMargin(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding).isActive = true
return self
}
@discardableResult
func lockToRight(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -padding).isActive = true
return self
}
@discardableResult
func hugRight(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.leftAnchor.constraint(equalTo: view.rightAnchor, constant: padding).isActive = true
return self
}
@discardableResult
func hugLeft(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.rightAnchor.constraint(equalTo: view.leftAnchor, constant: padding).isActive = true
return self
}
@discardableResult
func hugBottom(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.topAnchor.constraint(equalTo: view.bottomAnchor, constant: padding).isActive = true
return self
}
@discardableResult
func hugTop(ofView view: UIView, withPadding padding: CGFloat = 0) -> Self {
self.bottomAnchor.constraint(equalTo: view.topAnchor, constant: -padding).isActive = true
return self
}
@discardableResult
func set(aspectRatio: CGFloat, toWidthOfView view: UIView) -> Self {
self.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: aspectRatio).isActive = true
return self
}
/**
Lock the horizontal center of the receiver to the one of the provied view.
- Parameter view: The view which horizontal center to lock to the receiver's.
- Parameter padding: An optional offset to apply.
- Returns: The receiver.
*/
@discardableResult
func lockToCenterX(ofView view: UIView, offset: CGFloat = 0) -> Self {
NSLayoutConstraint.activate([
self.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: offset),
])
return self
}
/**
Lock the vertical center of the receiver to the one of the provied view.
- Parameter view: The view which horizontal center to lock to the receiver's.
- Parameter padding: An optional offset to apply.
- Returns: The receiver.
*/
@discardableResult
func lockToCenterY(ofView view: UIView, offset: CGFloat = 0) -> Self {
NSLayoutConstraint.activate([
self.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset),
])
return self
}
/**
Lock the width of the receiver with the one of the provided view.
- Parameter view: The view which width to lock the receiver's to.
- Parameter multiplier: An optional multiplier applied to the `view`'s width creating the receiver's width.
- Parameter constant: A constant width modifier.
- Returns: The receiver.
*/
@discardableResult
func lockToWidth(ofView view: UIView, withMultiplier multiplier: CGFloat = 1, constant: CGFloat = 0) -> Self {
self.widthAnchor.constraint(
equalTo: view.widthAnchor,
multiplier: multiplier,
constant: constant
).isActive = true
return self
}
/**
Lock the height of the receiver with the one of the provided view.
- Parameter view: The view which height to lock the receiver's to.
- Parameter multiplier: An optional multiplier applied to the `view`'s height creating the receiver's width.
- Parameter constant: A constant value to apply to the height.
- Returns: The receiver.
*/
@discardableResult
func lockToHeight(ofView view: UIView, withMultiplier multiplier: CGFloat = 1, constant: CGFloat = 0) -> Self {
self.heightAnchor.constraint(equalTo: view.heightAnchor,
multiplier: multiplier,
constant: constant).isActive = true
return self
}
@discardableResult
func setHeight(
to constant: CGFloat,
withPriority priority: UILayoutPriority = UILayoutPriority.defaultHigh
) -> Self {
let constraint = self.heightAnchor.constraint(equalToConstant: constant)
constraint.priority = priority
NSLayoutConstraint.activate([constraint])
return self
}
@discardableResult
func setWidth(
to constant: CGFloat,
withPriority priority: UILayoutPriority = UILayoutPriority.defaultHigh
) -> Self {
let constraint = self.widthAnchor.constraint(equalToConstant: constant)
constraint.priority = priority
NSLayoutConstraint.activate([constraint])
return self
}
@discardableResult
func makeSquare(fromHeight: Bool = true) -> Self {
let decidingAnchor = fromHeight ? heightAnchor : widthAnchor
let dependentAnchor = fromHeight ? widthAnchor : heightAnchor
decidingAnchor.constraint(equalTo: dependentAnchor).isActive = true
return self
}
@discardableResult
func lockBaseline(with other: UIView) -> Self {
self.firstBaselineAnchor.constraint(equalTo: other.firstBaselineAnchor).isActive = true
return self
}
/**
Add the provided view as a subview of the receiver.
- Parameter view: The view to add as a subview.
- Returns: The newly added subview.
*/
@discardableResult
func add<T>(view: T) -> T where T: UIView {
self.addSubview(view)
return view
}
@discardableResult
func setHugging(priority: UILayoutPriority, for axis: UILayoutConstraintAxis) -> Self {
self.setContentHuggingPriority(priority, for: axis)
return self
}
@discardableResult
func setCompressionResistance(priority: UILayoutPriority, for axis: UILayoutConstraintAxis) -> Self {
self.setContentCompressionResistancePriority(priority, for: axis)
return self
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment