SkillAgentSearch skills...

PinLayout

Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]

Install / Use

/learn @layoutBox/PinLayout

README

<p align="center"> <a href="https://github.com/layoutBox/PinLayout"><img src="docs/pinlayout-logo-text.png" width="200" /></a> </p> <p align="center"> <a href="https://github.com/layoutBox/PinLayout"><img src="https://img.shields.io/badge/platforms-iOS%20%7C%20tvOS%20%7C%20macOS-red.svg"/></a> <a href="https://github.com/layoutBox/PinLayout"><img src="https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-red.svg"/></a> </p> <p align="center"> <a href='https://cocoapods.org/pods/PinLayout'><img src="https://img.shields.io/cocoapods/v/PinLayout.svg?style=flat" /> <a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" /></a> <a href="https://swift.org/package-manager/"><img src="https://camo.githubusercontent.com/57aa80b42087a088cdf607fb98c0224bccf1b441/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73706d2d636f6d70617469626c652d627269676874677265656e2e7376673f7374796c653d666c6174" /></a> <a href="https://github.com/layoutBox/PinLayout/actions/workflows/github-actions-ci.yml"><img src="https://github.com/layoutBox/PinLayout/actions/workflows/github-actions-ci.yml/badge.svg?branch=master"/></a> <!-- <a href="https://codecov.io/gh/layoutBox/PinLayout"><img src="https://codecov.io/gh/layoutBox/PinLayout/branch/master/graph/badge.svg"/></a> --> <a href="https://raw.githubusercontent.com/layoutBox/PinLayout/master/LICENSE"><img src="https://img.shields.io/cocoapods/l/PinLayout.svg" /></a> </p>

Extremely Fast views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. PinLayout can layouts UIView, NSView and CALayer.

"No Auto layout constraints attached"

Requirements

  • iOS 9.0+ / tvOS 9.0+ / macOS 10.9+
  • Swift 5.x / 4 / 3 / Objective-C
  • Xcode 13 / 12 / 11 / 10

Recent changes/features

Content

<br>

:pushpin: PinLayout is actively updated. So please come often to see latest changes. You can also Star it to be able to retrieve it easily later.

PinLayout and layoutBox

<a href="https://github.com/layoutBox/PinLayout"><img src="docs/images/pinlayout_plus_layoutBox.png" width="200"/></a>

PinLayout is part of the layoutBox organization containing few Open Source projects related to layout using Swift. See layoutBox.

PinLayout + Autolayout

You don't need to choose, you can layout some views using PinLayout and some other with autolayout. Your views just to need to implement the autolayout intrinsicContentSize properties.

<br>

<a name="intro_usage_examples"></a>

Introduction examples

Example 1:

This example layout an image, a UISegmentedControl, a label and a line separator. This example adjusts its content to match the device's size and orientation changes.

  • UIImageView's size is 100x100 and layouted below the UINavigationBar with a margin of 10 pixels all around.
  • UISegmentedControl is at the right of the logo image, use the remaining horizontal space with a left and right margin of 20 pixels.
  • UILabel is below the UISegmentedControl with a top margin of 10 pixels. Its width matched the UISegmentedControl's width. The label is multiline, so its height must be adjusted to fit its width.
  • Separator is below the UIImageView and the UILabel, i.e. below the tallest one. The separator has a top margin of 10 pixels, left-aligned to the UIImageView and right-aligned to the UISegmentedControl.

<a href="https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Intro/IntroView.swift"><img src="docs/images/pinlayout_intro_example_iphonex.png"/></a>

override func layoutSubviews() {
   super.layoutSubviews() 
   let padding: CGFloat = 10
    
   logo.pin.top(pin.safeArea).left(pin.safeArea).width(100).aspectRatio().margin(padding)
   segmented.pin.after(of: logo, aligned: .top).right(pin.safeArea).marginHorizontal(padding)
   textLabel.pin.below(of: segmented, aligned: .left).width(of: segmented).pinEdges().marginTop(10).sizeToFit(.width)
   separatorView.pin.below(of: [logo, textLabel], aligned: .left).right(to: segmented.edge.right).marginTop(10)
}
  • 4 views, 4 lines
  • PinLayout expose the safeAreaInsets through UIView.pin.safeArea, this property support not only iOS 11, but is also backward compatible for earlier iOS releases (7/8/9/10). See safeAreaInsets support for more information.
  • PinLayout doesn't use auto layout constraints, it is a framework that manually layout views. For that reason you need to update the layout inside either UIView.layoutSubviews() or UIViewController.viewDidLayoutSubviews() to handle container size's changes, including device rotation. You'll also need to handle UITraitCollection changes for app's that support multitasking. In the example above PinLayout's commands are inside UIView's layoutSubviews() method.
  • This example is available in the Examples App. See example complete source code
<br/>
Example 2:

This example shows how easily PinLayout can adjust its layout based on the view's container size.

  • If the container's width is smaller than 500 pixels, the label takes the full width and the UISegmentedControl is placed below it.
  • If the container's width is greater or equal to 500 pixels, the UISegmentedControl is at the top-right corner and the label takes the remaining horizontal space.

<a href="https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AdjustToContainer/Subviews/ChoiceSelectorView.swift"><img src="docs/pinlayout_example_adjust_to_container2.png" width="640"/></a>

  let margin: CGFloat = 12
        
  if frame.width < 500 {
      textLabel.pin.top().horizontally().margin(margin).sizeToFit(.width)
      segmentedControl.pin.below(of: textLabel).right().margin(margin)
  } else {
      segmentedControl.pin.top().right().margin(margin)
      textLabel.pin.top().left().before(of: segmentedControl).margin(margin).sizeToFit(.width)
  }

:pushpin: This example is available in the Examples App. See example complete source code

<a name="introduction"></a>

PinLayout principles and philosophy

  • Manual layouting (doesn't rely on auto layout).
  • PinLayout exist to be simple and fast as possible! In fact, it is fast as manual layouting. See performance results below.
  • Full control: You're in the middle of the layout process, no magic black box.
  • Layout one view at a time. Make it simple to code and debug.
  • Concise syntax. Layout most views using a single line.
  • See the complete list here....

<a name="performance"></a>

PinLayout's Performance

PinLayout's performance has been measured using the Layout Framework Benchmark.

As you can see in the following chart, PinLayout are faster or equal to manual layouting, and between 8x and 12x faster than auto layout, and this for all types of iPhone (5S/6/6S/7/8/X)

See here for more details, results and explanation of the benchmark.

<p align="center"> <a href="docs/Benchmark.md"> <img src="docs/Benchmark/benchmark_comparison_all_small.png" width=660/> </a> </p>

<a name="documentati

View on GitHub
GitHub Stars2.4k
CategoryDevelopment
Updated16h ago
Forks147

Languages

Swift

Security Score

100/100

Audited on Mar 27, 2026

No findings