PinLayout Documentation

repository·master·Indexed 25 days ago

https://github.com/layoutbox/pinlayout

A fast, manual layout framework for iOS, tvOS, and macOS that provides a concise, chainable syntax for layouting UIViews, NSViews, and CALayers without Auto Layout constraints. It supports relative positioning, RTL languages, and responsive designs, requiring iOS 9.0+, tvOS 9.0+, or macOS 10.9+.

Tokens
14.3K
Snippets
33
Records
70
Agent score
81%

What's inside PinLayout

  1. PinLayout Performance Benchmarks

    master

    PinLayout is highly optimized for performance, particularly in complex list scenarios like UICollectionView and UITableView. Benchmarks conducted using the Layout Framework Benchmark show that PinLayout is:

    • Faster or equal to Manual Layout (setting UIView.frame directly).
    • 8x to 12x faster than Auto Layout across various iPhone models (including 5S through X).

    These results hold true for multi-pass layout scenarios where cell counts increase per pass.

  2. Understand PinLayout's core principles and philosophy

    master

    PinLayout is a manual layout engine designed for speed and simplicity. Unlike Auto Layout, it does not use constraints or a complex solver. Key characteristics include:

    • Manual Layouting: It relies on manual frame calculations rather than Auto Layout constraints, making it as fast as manual layouting.
    • Full Control: You have direct control over the layout process. You can use standard Swift control flow (if/switch/guard) and loops (for/while/forEach) to handle device orientation, trait collections, or animations.
    • Statelessness: PinLayout does not add stored properties to UIView or NSView. It simply computes the view's frame. This allows you to mix PinLayout with other frameworks like Auto Layout or Flexbox without conflicts.
    • One View at a Time: The mental model is to layout views individually, making the code easier to debug.
    • Animation Friendly: PinLayout starts calculations from the view's current frame. This allows you to set a view's size during initialization (e.g., view.pin.width(100).height(200)) and subsequently only update its position (e.g., view.pin.top(10).left(20)), which is ideal for smooth animations.
    • Low Intrusiveness: It only adds three properties to existing iOS classes: UIView.pin, UIView.anchor, and UIView.edge.
  3. Use PinLayout with macOS (NSView)

    master

    PinLayout supports NSView on macOS with the following constraints:

    • Coordinate System: Only supports views with a flipped coordinate system (isFlipped == true).
    • sizeToFit(:FitType): Supported only for instances inheriting from NSControl. For custom NSView subclasses, conform to the SizeCalculable protocol and implement sizeThatFits(:CGSize).
    • Unavailable Properties: pin.safeArea and pin.readableMargins are not available in AppKit.
    • Unavailable Methods: aspectRatio() with no parameters is not supported.
  4. Understand PinLayout's stateless nature for animations

    master

    PinLayout is stateless, meaning it always calculates layout starting from the view's current position and size (frame). Because of this, you do not need to reset any properties to animate a view. You can modify only the specific property you wish to animate within a standard UIView.animate block.

    UIView.animate(withDuration: 0.3) { 
       view.pin.width(30)
    }
  5. Handle UIView transforms with pin vs pinFrame

    master

    When a UIView has a transform applied (scaling, rotation, etc.), you must choose between pin and pinFrame to determine how the layout is applied relative to that transform.

    UIView.pin (Pre-transform)

    • Applies layout to the non-transformed view.
    • The layout is calculated before the transform is applied.
    • When layouting relative to a transformed view (e.g., below(of:)), PinLayout uses the untransformed size and position of the reference view.

    UIView.pinFrame (Post-transform)

    • Applies layout to the transformed view.
    • The layout is calculated after the transform is applied.
    • When layouting relative to a transformed view, PinLayout uses the transformed size and position of the reference view.

    Comparison Summary

    Scenariopin behaviorpinFrame behavior
    RotationLayouted, then rotatedRotated, then layouted
    Relative LayoutUses untransformed reference size/posUses transformed reference size/pos
    // Using pin (pre-transform)
    view.transform = .init(rotationAngle: CGFloat.pi / 2)
    view.pin.center().width(100).height(50)
    
    // Using pinFrame (post-transform)
    view.transform = .init(rotationAngle: CGFloat.pi / 2)
    view.pinFrame.center().width(100).height(50)
  6. Use PinLayout with CALayer

    master

    PinLayout can layout CALayer objects.

    Limitations:

    • sizeToFit(:FitType) is not supported. To enable it, conform your custom CALayer subclass to the SizeCalculable protocol and implement sizeThatFits(:CGSize).
    • pin.safeArea and pin.readableMargins are not available.
    • aspectRatio() with no parameters is not supported.
    aLayer = CALayer()
    bLayer = CALayer()
    view.layer.addSublayer(aLayer)
    view.layer.addSublayer(bLayer)
    
    aLayer.pin.top(10).left(10).width(20%).height(80%)
    bLayer.pin.below(of: aLayer, aligned: .left).size(of: aLayer)
  7. How RTL support works in PinLayout

    master

    PinLayout supports Right-to-Left (RTL) languages by providing semantic alternatives to directional methods. Instead of using methods containing left or right, you should use methods containing start and end.

    Using start and end allows you to position views based on their logical position in the layout flow rather than a fixed physical side. This ensures that your layout automatically adapts to the user's language settings (e.g., a view pinned to the start will appear on the left in LTR mode and on the right in RTL mode).

  8. How horizontal and vertical margins are applied

    master

    PinLayout applies margins by either moving the view or reducing its size, depending on which attributes are pinned.

    Horizontal Margins

    View's pinned attributesLeft MarginRight Margin
    LeftMove view right-
    Left and WidthMove view right-
    Right-Move view left
    Right and Width-Move view left
    Left and RightReduce width to apply left marginReduce width to apply right margin
    hCenterMove view rightMove view left

    Vertical Margins

    View's pinned attributesTop MarginBottom Margin
    TopMove view down-
    Top and HeightMove view down-
    Bottom-Move view up
    Bottom and Height-Move view up
    Top and BottomReduce height to apply top marginReduce height to apply bottom margin
    vCenterMove view downMove view up

    Note: - indicates the margin is not applied.

  9. Implement responsive layouts with Adjust To Container

    master
    PinLayout can be used to adjust layouts dynamically based on available space. For example, you can change the orientation of elements (e.g., moving a UISegmentedControl from a horizontal line to below a label) when the container width falls below a specific threshold (like 500 pixels).
  10. Core concepts of PinLayout

    master

    PinLayout is a manual layout framework designed for speed and control. Unlike Auto Layout, it does not use constraints. Instead, it performs manual layouting, making it as fast as writing manual frame calculations.

    Key Principles:

    • Manual Layouting: Does not rely on Auto Layout constraints.
    • Full Control: No 'magic' black box; you are in control of the layout process.
    • One View at a Time: Encourages simple, debuggable code by layouting views individually.
    • Concise Syntax: Most views can be laid out using a single, chainable line of code.

    Important Implementation Note: Because PinLayout performs manual layout, you must trigger your layout code inside UIView.layoutSubviews() or UIViewController.viewDidLayoutSubviews() to handle changes in container size, such as device rotation or multitasking split-view changes.

  11. Handle iOS safeAreaInsets with PinLayout

    master

    To support iOS 11+ features like the iPhone X landscape mode, you should manage UIView.safeAreaInsets.

    Recommended Pattern:

    1. Create a contentView that contains all child views.
    2. Adjust this contentView to match the safeAreaInsets using either the standard UIView.safeAreaInsets or PinLayout's UIView.pin.safeArea.

    Note: Only the UIViewController's main view needs to handle safeAreaInsets; sub-views typically do not need to handle them directly.

  12. Use PinLayout with Auto Layout

    master
    You can mix PinLayout and Auto Layout in the same project. If you have views that rely on Auto Layout, ensure they implement the intrinsicContentSize property. PinLayout will then be able to interact with them as part of the manual layout process.