2026-08-29 19:22:12 -03:00
|
|
|
# LCEssentials — UIKit
|
|
|
|
|
|
|
|
|
|
UIKit-era helpers: programmatic layout & constraints, view/control extensions,
|
|
|
|
|
navigation, table/collection helpers, and drop-in components (image picker, image
|
|
|
|
|
zoom, snackbar, GIF loading).
|
|
|
|
|
|
|
|
|
|
Foundation/value-type helpers are in [Extensions.md](Extensions.md); SwiftUI
|
|
|
|
|
helpers in [SwiftUI.md](SwiftUI.md).
|
|
|
|
|
|
|
|
|
|
Every section is a collapsible block — click a heading to expand it.
|
|
|
|
|
|
|
|
|
|
## Contents
|
|
|
|
|
|
|
|
|
|
- [Layout & Constraints](#layout--constraints)
|
|
|
|
|
- [Views & Controls](#views--controls)
|
|
|
|
|
- [Navigation & Controllers](#navigation--controllers)
|
|
|
|
|
- [Collections & Tables](#collections--tables)
|
|
|
|
|
- [Media & Components](#media--components)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Layout & Constraints
|
|
|
|
|
|
2026-08-29 19:31:43 -03:00
|
|
|
<details>
|
|
|
|
|
<summary><b>UIView</b> — programmatic constraints, chainable anchors</summary>
|
|
|
|
|
|
|
|
|
|
### `enum AnchorType`
|
|
|
|
|
The anchor to pin when using `setConstraintsTo`. Cases: `all`, `top`, `bottom`,
|
|
|
|
|
`leading`, `trailing`, `left`, `right`, `centerX`, `centerY`, `width`, `heigth`
|
|
|
|
|
*(sic)*, `topToBottom`, `bottomToTop`, `leadingToTrailing`, `trailingToLeading`,
|
|
|
|
|
plus `…GreaterThanOrEqualTo` / `…LessThanOrEqualTo` variants.
|
|
|
|
|
|
|
|
|
|
### `@discardableResult func setConstraintsTo(parentView: UIView, anchorType: AnchorType, value: CGFloat, safeArea: Bool = false) -> Self`
|
|
|
|
|
Activate one constraint against `parentView`. Remembers `parentView` (in
|
|
|
|
|
`viewReference`) so follow-up calls can omit it. `safeArea: true` pins top/bottom
|
|
|
|
|
to the safe-area guide (iOS 11+).
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
card.addSubview(label)
|
|
|
|
|
label.setConstraintsTo(parentView: card, anchorType: .top, value: 12, safeArea: false)
|
|
|
|
|
.setConstraints(.leading, 16)
|
|
|
|
|
.setConstraints(.trailing, -16)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `@discardableResult func setConstraintsTo(_ parentView:_ anchorType:_ value:_ safeArea: Bool = false) -> Self`
|
|
|
|
|
Positional-argument shorthand for the above.
|
|
|
|
|
|
|
|
|
|
### `@discardableResult func setConstraintsTo(anchorType: AnchorType, value: CGFloat, safeArea: Bool = false) -> UIView`
|
|
|
|
|
Reuse the last `parentView` (`viewReference`). **Traps** with `fatalError` if no
|
|
|
|
|
`parentView` was set first.
|
|
|
|
|
|
|
|
|
|
### `@discardableResult func setConstraints(_ anchorType: AnchorType, _ value: CGFloat, _ safeArea: Bool = false) -> UIView`
|
|
|
|
|
Positional shorthand for the reuse form — the one you chain.
|
|
|
|
|
|
|
|
|
|
### `func setConstraints(_ toScrollView: UIScrollView, direction: UICollectionView.ScrollDirection = .vertical)`
|
|
|
|
|
Pin `self` as the single content view of a scroll view (edges + matching
|
|
|
|
|
width/height, with a low-priority constraint on the scroll axis). Traps if
|
|
|
|
|
`self` is itself a `UIScrollView`.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
scrollView.addSubview(content)
|
|
|
|
|
content.setConstraints(scrollView, direction: .vertical)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Constraint accessors
|
|
|
|
|
`widthConstraint`, `heightConstraint`, `leadingConstraint`, `trailingConstraint`,
|
|
|
|
|
`topConstraint`, `bottomConstraint`, `centerXConstraints`, `centerYConstraints` —
|
|
|
|
|
the first matching `NSLayoutConstraint` found by walking up the hierarchy.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
box.widthConstraint?.constant = 120
|
|
|
|
|
UIView.animate(withDuration: 0.2) { self.view.layoutIfNeeded() }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func findConstraint(attribute: NSLayoutConstraint.Attribute, for view: UIView) -> NSLayoutConstraint?`
|
|
|
|
|
Search self and ancestors for a constraint on `attribute` involving `view`.
|
|
|
|
|
|
|
|
|
|
### `func constraints(on anchor:) -> [NSLayoutConstraint]`
|
|
|
|
|
Constraints touching a given `NSLayoutYAxisAnchor` / `XAxisAnchor` / `Dimension` of `self`.
|
|
|
|
|
|
|
|
|
|
### `@discardableResult func setHeight(size:) -> Self` / `setHeight(min:)` / `setWidth(size:)` / `setWidth(min:)`
|
|
|
|
|
Activate a fixed or minimum dimension constraint.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
avatar.setWidth(size: 44).setHeight(size: 44)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func setWidth(_ toView: UIView? = nil, constant: CGFloat, _ multiplier: CGFloat = 0) -> Self` / `setHeight(...)`
|
|
|
|
|
Dimension relative to another view (`multiplier`) or fixed (`multiplier == 0`).
|
|
|
|
|
|
|
|
|
|
### Frame setters
|
|
|
|
|
`setX(x:)`, `setY(y:)`, `setFrameWidth(width:)`, `setFrameHeight(height:)` — mutate
|
|
|
|
|
`self.frame` directly (manual layout, not Auto Layout).
|
|
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary><b>UIView</b> — hierarchy, appearance, effects</summary>
|
|
|
|
|
|
|
|
|
|
### `static var className: String`
|
|
|
|
|
`String(describing: self)`.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
UIButton.className // "UIButton"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func addSubview(_ subview:, translatesAutoresizingMaskIntoConstraints: Bool = false)` / `addSubviews(_ subviews: [UIView], …)`
|
|
|
|
|
Add a view (or many) and set `translatesAutoresizingMaskIntoConstraints` in one call.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
view.addSubviews([header, body, footer]) // all ready for Auto Layout
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func subviews<T>(ofType _: T.Type) -> [T]`
|
|
|
|
|
All descendants of a type, recursively.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
formView.subviews(ofType: UITextField.self)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func findAView<T>(_ ofType: T.Type) -> T?`
|
|
|
|
|
First descendant of a type.
|
|
|
|
|
|
|
|
|
|
### `var parentViewController: UIViewController?`
|
|
|
|
|
Nearest owning view controller (walks the responder chain).
|
|
|
|
|
|
|
|
|
|
### `var borderColor: UIColor?` / `var borderWidth: CGFloat` / `var cornerRadius: CGFloat`
|
|
|
|
|
Layer border/corner shortcuts (`cornerRadius` also sets `masksToBounds`).
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
card.cornerRadius = 12
|
|
|
|
|
card.borderWidth = 1
|
|
|
|
|
card.borderColor = .separator
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func setRadius(top: Bool, bottom: Bool, radius: CGFloat = 8)`
|
|
|
|
|
Round only the top and/or bottom corners.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
sheet.setRadius(top: true, bottom: false, radius: 16)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func applyShadow(color:offSet:radius:opacity:shouldRasterize: Bool = true, rasterizationScaleTo: = UIScreen.main.scale)` / `func removeShadow()`
|
|
|
|
|
Layer shadow with rasterisation on by default.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
card.applyShadow(color: .black, offSet: CGSize(width: 0, height: 2),
|
|
|
|
|
radius: 6, opacity: 0.15)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func insertBlurView(style: UIBlurEffect.Style, color: UIColor = .black, alpha: CGFloat = 0.9)`
|
|
|
|
|
Insert a full-bleed `UIVisualEffectView` behind the content.
|
|
|
|
|
|
|
|
|
|
### `func drawCircle(inCoord x:y:with radius:strokeColor: = .red, fillColor: = .gray, isEmpty: Bool = false) -> [String: Any]`
|
|
|
|
|
Add a circular `CAShapeLayer`; returns `["path": UIBezierPath, "layer": CAShapeLayer]`.
|
|
|
|
|
|
|
|
|
|
### `var isRightToLeft: Bool`
|
|
|
|
|
Effective RTL layout direction.
|
|
|
|
|
|
|
|
|
|
### `var screenshot: UIImage?` / `func asImage() -> UIImage`
|
|
|
|
|
Render the view to an image (`screenshot` via the legacy context, `asImage` via `UIGraphicsImageRenderer`).
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
let png = chartView.asImage().pngData()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `var globalPoint: CGPoint?` / `var globalFrame: CGRect?` / `var absolutePosition: CGRect`
|
|
|
|
|
Origin/frame converted to window coordinates.
|
|
|
|
|
|
|
|
|
|
### `func fadeIn(withDuration: TimeInterval = 1, withDelay: TimeInterval = 0, completionHandler: @escaping (Bool) -> Void)` / `func fadeOut(...)`
|
|
|
|
|
Animate `alpha` to 1 / 0. *(Completion-handler API — pre-dates async/await.)*
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
overlay.fadeOut { _ in overlay.removeFromSuperview() }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `var viewReference: UIView?`
|
|
|
|
|
Scratch reference used internally by the chained `setConstraintsTo` calls.
|
|
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary><b>GradientOrientation / EnumBorderSide</b></summary>
|
|
|
|
|
|
|
|
|
|
### `enum GradientOrientation`
|
|
|
|
|
`topRightBottomLeft`, `topLeftBottomRight`, `horizontal`, `vertical` — maps to a
|
|
|
|
|
`CAGradientLayer` start/end point pair. Passed to gradient helpers elsewhere in
|
|
|
|
|
the package.
|
|
|
|
|
|
|
|
|
|
### `enum EnumBorderSide`
|
|
|
|
|
`top`, `bottom`, `left`, `right` — which edge to draw a single-side border on.
|
|
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary><b>UIStackView</b> — convenience init, bulk arranged-subview ops (iOS 9+)</summary>
|
|
|
|
|
|
|
|
|
|
### `convenience init(arrangedSubviews: [UIView]? = nil, axis: = .vertical, spacing: = 0, alignment: = .fill, distribution: = .fill, layoutMargins: = .zero, isMarginsRelative: Bool = true)`
|
|
|
|
|
One-call configured stack view.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
let stack = UIStackView(arrangedSubviews: [title, subtitle],
|
|
|
|
|
axis: .vertical, spacing: 4)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `func addArrangedSubviews(_ views: [UIView], translateAutoresizing: Bool = false)`
|
|
|
|
|
Add many arranged subviews, setting their autoresizing flag.
|
|
|
|
|
|
|
|
|
|
### `func removeAllArrangedSubviews(deactivateConstraints: Bool = true)`
|
|
|
|
|
Remove and dispose every arranged subview.
|
|
|
|
|
|
|
|
|
|
### `func removeSubview(view: UIView, deactivateConstraints: Bool = true)`
|
|
|
|
|
Remove one arranged subview (optionally deactivating its constraints and removing from the hierarchy).
|
|
|
|
|
|
|
|
|
|
### `func addSpace(_ size: CGFloat, backgroundColor: UIColor = .clear)`
|
|
|
|
|
Insert a fixed-size spacer view sized along the stack's axis.
|
|
|
|
|
|
|
|
|
|
```swift
|
|
|
|
|
stack.addArrangedSubviews([row1, row2])
|
|
|
|
|
stack.addSpace(24)
|
|
|
|
|
stack.addArrangedSubview(row3)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
> `NSLayoutConstraint` helpers (`constraintWithMultiplier`, `matches(view:anchor:)`)
|
|
|
|
|
> and `[NSLayoutConstraint].filtered(view:anchor:)` are `internal` — used by the
|
|
|
|
|
> `UIView.constraints(on:)` accessors above, not called directly.
|
2026-08-29 19:22:12 -03:00
|
|
|
|
|
|
|
|
## Views & Controls
|
|
|
|
|
|
|
|
|
|
<!-- batch 10 -->
|
|
|
|
|
|
|
|
|
|
## Navigation & Controllers
|
|
|
|
|
|
|
|
|
|
<!-- batch 11 -->
|
|
|
|
|
|
|
|
|
|
## Collections & Tables
|
|
|
|
|
|
|
|
|
|
<!-- batch 12 -->
|
|
|
|
|
|
|
|
|
|
## Media & Components
|
|
|
|
|
|
|
|
|
|
<!-- batch 13 -->
|