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.

    Note

    During the transition from Blueprint’s legacy layout system to Caffeinated Layout, the Layout protocol is composed of two sets of layout methods: LegacyLayout and CaffeinatedLayout. While this documentation focuses on the newer layout API, you must currently implement both. Fortunately, the methods are similar, and you may be able to reuse logic.

    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. The traits are of the Layout protocol’s associated type Traits, and each subelement can have a distinct Traits value assigned. You can set this in the configure block of init(layout:configure:), when you call add(traits:key:element:). If you do not specify a Traits type for your layout, it defaults to the void type, ().

    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. Your layout container accesses the traits for a subelement by calling traits(forLayoutType:) on the LayoutSubelement proxy.

    Note

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

    Declaration

    Swift

    public protocol Layout : CaffeinatedLayout, LegacyLayout
  • Declaration

    Swift

    public protocol LegacyLayout
  • Declaration

    Swift

    public protocol CaffeinatedLayout
  • 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, LegacySingleChildLayout
  • Declaration

    Swift

    public protocol LegacySingleChildLayout
  • Declaration

    Swift

    public protocol CaffeinatedSingleChildLayout
  • 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