Skip to content

Instantly share code, notes, and snippets.

@rib3ye
Last active March 2, 2019 01:58
Show Gist options
  • Save rib3ye/0f48544672a0fbca3e219aa8c58d4011 to your computer and use it in GitHub Desktop.
Save rib3ye/0f48544672a0fbca3e219aa8c58d4011 to your computer and use it in GitHub Desktop.
A small extension to make creating UIView anchors less painful
//
// UIView+extension.swift
//
// Created by Noah Tsutsui on 7/25/18.
// Copyright © 2018 Noah Tsutsui. All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import UIKit
extension UIView {
func anchor(horizontalCenter: Bool, horizontalCenterAnchor: NSLayoutXAxisAnchor?, verticalCenter: Bool, verticalCenterAnchor: NSLayoutYAxisAnchor?, leadingAnchor: NSLayoutXAxisAnchor?, trailingAnchor: NSLayoutXAxisAnchor?, topAnchor: NSLayoutYAxisAnchor?, rightAnchor: NSLayoutXAxisAnchor?, bottomAnchor: NSLayoutYAxisAnchor?, leftAnchor: NSLayoutXAxisAnchor?, width: CGFloat?, height: CGFloat?, topPadding: CGFloat, rightPadding: CGFloat, bottomPadding: CGFloat, leftPadding: CGFloat){
self.translatesAutoresizingMaskIntoConstraints = false
if horizontalCenter {
if let horizontalCenterAnchor = horizontalCenterAnchor {
self.centerXAnchor.constraint(equalTo: horizontalCenterAnchor, constant: leftPadding+rightPadding).isActive = true
if rightAnchor != nil || leftAnchor != nil || leadingAnchor != nil || trailingAnchor != nil {
print("You have set horizontal centerting in addition to left/right/leading/trailing anchor(s). Is this intentional?")
}
}
}
if leftAnchor != nil && leadingAnchor != nil {
print("You have both a leading and left anchor, you can only use one. Probably a verbose warning from XCode is below?")
}
if trailingAnchor != nil && rightAnchor != nil {
print("You have both a tailing and right anchor, you can only use one. Probably a verbose warning from XCode is below?")
}
if let rightAnchor = rightAnchor {
self.rightAnchor.constraint(equalTo: rightAnchor, constant: -rightPadding).isActive = true
}
if let leftAnchor = leftAnchor {
self.leftAnchor.constraint(equalTo: leftAnchor, constant: leftPadding).isActive = true
}
if let leadingAnchor = leadingAnchor {
self.leadingAnchor.constraint(equalTo: leadingAnchor, constant: leftPadding).isActive = true
}
if let trailingAnchor = trailingAnchor {
self.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -rightPadding).isActive = true
}
if verticalCenter {
if let verticalCenterAnchor = verticalCenterAnchor {
self.centerYAnchor.constraint(equalTo: verticalCenterAnchor, constant: topPadding + bottomPadding).isActive = true
if topAnchor != nil || bottomAnchor != nil {
print("You have either top or bottom anchor in addition to centerYAnchor, is this intentional?")
}
}
}
if let topAnchor = topAnchor {
self.topAnchor.constraint(equalTo: topAnchor, constant: topPadding).isActive = true
}
if let bottomAnchor = bottomAnchor {
self.bottomAnchor.constraint(equalTo: bottomAnchor, constant: bottomPadding).isActive = true
}
if let width = width {
if width > 0 {
self.widthAnchor.constraint(equalToConstant: width).isActive = true
}
}
if let height = height {
if height > 0 {
self.heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
}
}
@rib3ye
Copy link
Author

rib3ye commented Jul 25, 2018

Better UIView Anchors

A simple UIView extension that makes anchors suck less.

Looks like...

func anchor(
  horizontalCenter: Bool, 
  horizontalCenterAnchor: NSLayoutXAxisAnchor?, 
  verticalCenter: Bool, 
  verticalCenterAnchor: NSLayoutYAxisAnchor?, 
  leadingAnchor: NSLayoutXAxisAnchor?, 
  trailingAnchor: NSLayoutXAxisAnchor?, 
  topAnchor: NSLayoutYAxisAnchor?, 
  rightAnchor: NSLayoutXAxisAnchor?, 
  bottomAnchor: NSLayoutYAxisAnchor?, 
  leftAnchor: NSLayoutXAxisAnchor?, 
  width: CGFloat?, 
  height: CGFloat?, 
  topPadding: CGFloat, 
  rightPadding: CGFloat, 
  bottomPadding: CGFloat, 
  leftPadding: CGFloat
)

Cool things

Automatically applies isActive = true and translatesAutoresizingMaskIntoConstraints = false

More friendly warnings when...

  • Attempting to apply left/right and leading/trailing at the same time.
  • Attempting to apply a top/bottom anchor to a centerYAnchor, of
    likewise, a left/right/leading/trailing anchor to a centerXAnchor.

Usage

Simply place UIView+Extension.swift in your project or append to the bottom of your ViewController.

Now you can:

myBeautifulView.anchor(
  horizontalCenter: true, 
  horizontalCenterAnchor: view.safeAreaLayoutGuide.centerXAnchor, 
  verticalCenter: false, 
  verticalCenterAnchor: nil, 
  leadingAnchor: nil, 
  trailingAnchor: nil, 
  topAnchor: view.safeAreaLayoutGuide.topAnchor, 
  rightAnchor: nil, 
  bottomAnchor: nil, 
  leftAnchor: nil, 
  width: 140, 
  height: 140, 
  topPadding: 40, 
  rightPadding: 0, 
  bottomPadding: 0, 
  leftPadding: 0
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment