Protocols

The following protocols are available globally.

  • Define AttributedText keys using this protocol. Keys must have an attribute name and an associated type for the attribute.

    After defining a key, enable dynamic member access to it by extending TextAttributeContainer with a property for getting and setting setting the value. This property should generally be optional, since the text may not have that property defined.

    See more

    Declaration

    Swift

    public protocol AttributedTextKey
  • Provides performance information for blueprint layouts and updates.

    See more

    Declaration

    Swift

    public protocol BlueprintViewMetricsDelegate : AnyObject
  • An element type which makes it easier to wrap an existing UIView instance that provides its own sizing via sizeThatFits. An instance of the view is used for sizing and measurement, so that you do not need to re-implement your own measurement.

    Note

    The sizing and measurement prototype view is kept alive for the lifetime of the containing application. Do not pass anything to the initializer of this type that you expect to be quickly released.

    Example

    If you were implementing a very basic Switch element, your implementation would look something like this:

    struct Switch : UIViewElement
    {
        var isOn : Bool
    
        typealias UIViewType = UISwitch
    
        func makeUIView() -> UISwitch {
            UISwitch()
        }
    
        func updateUIView(_ view: UISwitch, with context: UIViewElementContext) {
            view.isOn = self.isOn
        }
    }
    
    See more

    Declaration

    Swift

    public protocol UIViewElement : Element
  • Types used to identify alignment guides.

    Types conforming to AlignmentID have a corresponding alignment guide value, typically declared as a static constant property of HorizontalAlignment or VerticalAlignment.

    See more

    Declaration

    Swift

    public protocol AlignmentID
  • Defines a way for anElement to be implicitly converted into the conforming type (the child of a container). In practice, this allows us to pass an Element directly into the result builder without manually converting to Child (i.e. Converting Element -> StackLayout.Child.

    See more

    Declaration

    Swift

    public protocol ElementBuilderChild
  • A type that defines the geometry of a collection of elements.

    You traditionally arrange views in your app’s user interface using built-in layout containers like Row and Column. If you need more complex layout behavior, you can define a custom layout container by creating a type that conforms to the Layout protocol and implementing its required methods:

    You can define a basic layout type with only these two methods (see note below):

    struct BasicLayout: Layout {
        func sizeThatFits(
            proposal: SizeConstraint,
            subelements: Subelements,
            cache: inout ()
        ) -> CGSize {
            // Calculate and return the size of the layout container.
        }
    
        func placeSubelements(
            in size: CGSize,
            subelements: Subelements,
            cache: inout ()
        ) {
            // Tell each subelement where to appear.
        }
    }
    

    Add your layout to an element by passing it to the ElementContent initializer init(layout:configure:). If your layout has parameters that come from the element, pass them at initialization time. Use the configure block to add your element’s children to the content.

    struct BasicContainer: Element {
        var alignment: Alignment = .center
        var children: [Element]
    
        var content: ElementContent {
            ElementContent(layout: BasicLayout(alignment: alignment)) { builder in
                for child in children {
                    builder.add(element: child)
                }
            }
        }
    
        func backingViewDescription(with context: ViewDescriptionContext) -> ViewDescription? {
            nil
        }
    }
    

    If your layout is specialized for laying out a single subelement, you can use the SingleChildLayout protocol instead. It has similar methods, but is strongly typed for a single subelement instead of a collection.

    Interact with subelements through their proxies

    To perform layout, you need information about all of your container’s subelements, which are the child elements that your container arranges. While your layout can’t interact directly with its subelements, it can access a set of subelement proxies through the Subelements collection that each protocol method receives as an input parameter. That type is an alias for the LayoutSubelements collection type, which in turn contains LayoutSubelement instances that are the subelement proxies.

    You can get information about each subelement from its proxy, like its dimensions and traits. This enables you to measure subelements before you commit to placing them. You also assign a position to each subelement by calling its proxy’s place(at:anchor:size:) method. Call the method on each subelement from within your implementation of the layout’s placeSubelements(in:subelements:environment:cache:) method.

    Access layout traits

    Subelements may have traits that are specific to their container’s layout. Containers can choose to condition their behavior according to the traits of their subelements. For example, the Row and Column types allocate space for their subelements based in part on the grow and shrink priorities that you set on each child.

    Traits are set on each child in the configure block of init(layout:configure:), when you call add(traits:key:element:). Your layout container accesses the traits for a subelement by calling LayoutSubelement/subscript(key:) on the LayoutSubelement proxy. For more information about custom traits, see LayoutTraitsKey.

    Legacy layouts that support a single trait type can conform to SingleTraitLayout to define the trait type on the layout itself instead of using a key. These traits can be accessed with the traits(forLayoutType:) method.

    Note

    The Layout API, and its documentation, are modeled after SwiftUI’s Layout, with major differences noted.

    Declaration

    Swift

    public protocol Layout : CaffeinatedLayout
  • Declaration

    Swift

    public protocol CaffeinatedLayout
  • A key for accessing a layout trait value of a layout container’s subelements.

    If you create a custom layout by defining a type that conforms to the Layout protocol, you can also create custom layout traits that you set on individual subelements, and that your container can access to guide its layout behavior. Your custom traits resemble the built-in layout traits such as the grow and shrink priorities of Row and Column, but have a purpose that you define.

    To create a custom layout trait, first create a type that conforms to this protocol and implement the defaultValue property.

    Set layout traits

    Layout traits are set on subelements as part of the ElementContent. Use the initializer that provides a builder closure, and set layout traits on each subelement by calling the add(traitsType:traits:key:element:) method.

    enum MyPriorityKey: LayoutTraitsKey {
        static let defaultValue: CGFloat = 0
    }
    
    struct MyElement: Element {
        var children: [(element: Element, priority: CGFloat)]
    
        var content: ElementContent {
            ElementContent(layout: MyLayout()) { builder in
                for (element, priority) in children {
                    builder.add(
                        traitsType: MyPriorityKey.self,
                        traits: priority,
                        element: element
                    )
                }
            }
        }
    }
    

    Read layout traits

    To read the layout traits in your layout implementation, use the traits key type as an index on the LayoutSubelement. You can define a convenience property on LayoutSubelement to make it easier to read the value.

    extension LayoutSubelement {
        var myPriority: CGFloat {
            self[MyPriorityKey.self]
        }
    }
    
    struct MyLayout: Layout {
        func placeSubelements(
            in size: CGSize,
            subelements: Subelements,
            environment: Environment,
            cache: inout ()
        ) {
            for subelement in subelements {
                let myPriority = subelement.myPriority
                // place subelement based on myPriority
            }
        }
    }
    
    See more

    Declaration

    Swift

    public protocol LayoutTraitsKey
  • A type that defines the geometry of a single element.

    For convenience, you can implement this protocol instead of Layout when building a container that always has a single child element.

    For more information about writing custom layouts, see Layout.

    Declaration

    Swift

    public protocol SingleChildLayout : CaffeinatedSingleChildLayout
  • Declaration

    Swift

    public protocol CaffeinatedSingleChildLayout
  • A protocol for layouts that have a single associated trait type.

    Legacy layout implementations can implement this protocol to easily apply and read their traits without defining a custom trait key type.

    See more

    Declaration

    Swift

    public protocol SingleTraitLayout
  • Conforming types (Row and Column) act as StackLayout powered containers.

    This protocol should only be used by Row and Column elements (you should never add conformance to other custom types).

    See more

    Declaration

    Swift

    public protocol StackElement : Element
  • Conforming types can calculate the size that they require within a layout.

    See more

    Declaration

    Swift

    public protocol Measurable
  • Marker protocol used by generic extensions to native views (e.g. UIView).

    See more

    Declaration

    Swift

    public protocol NativeView
  • Conform to this protocol to handle links tapped in an AttributedLabel.

    Use the URLHandlerEnvironmentKey or Environment.urlHandler property to override the link handler in the environment.

    See more

    Declaration

    Swift

    public protocol URLHandler