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
See moreTextAttributeContainer
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.Declaration
Swift
public protocol AttributedTextKey
-
Provides performance information for blueprint layouts and updates.
See moreDeclaration
Swift
public protocol BlueprintViewMetricsDelegate : AnyObject
-
An element type which makes it easier to wrap an existing
UIView
instance that provides its own sizing viasizeThatFits
. 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:
See morestruct Switch : UIViewElement { var isOn : Bool typealias UIViewType = UISwitch func makeUIView() -> UISwitch { UISwitch() } func updateUIView(_ view: UISwitch, with context: UIViewElementContext) { view.isOn = self.isOn } }
Declaration
Swift
public protocol UIViewElement : Element
-
Types used to identify alignment guides.
Types conforming to
See moreAlignmentID
have a corresponding alignment guide value, typically declared as a static constant property ofHorizontalAlignment
orVerticalAlignment
.Declaration
Swift
public protocol AlignmentID
-
Defines a way for an
See moreElement
to be implicitly converted into the conforming type (the child of a container). In practice, this allows us to pass anElement
directly into the result builder without manually converting toChild
(i.e. ConvertingElement
->StackLayout.Child
.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
andColumn
. If you need more complex layout behavior, you can define a custom layout container by creating a type that conforms to theLayout
protocol and implementing its required methods:sizeThatFits(proposal:subelements:environment:cache:)
reports the sizes of the composite layout.placeSubelements(in:subelements:environment:cache:)
assigns positions to the container’s subelements.
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
initializerinit(layout:configure:)
. If your layout has parameters that come from the element, pass them at initialization time. Use theconfigure
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 theLayoutSubelements
collection type, which in turn containsLayoutSubelement
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’splaceSubelements(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
andColumn
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 ofinit(layout:configure:)
, when you calladd(traits:key:element:)
. Your layout container accesses the traits for a subelement by callingLayoutSubelement/subscript(key:)
on theLayoutSubelement
proxy. For more information about custom traits, seeLayoutTraitsKey
.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 thetraits(forLayoutType:)
method.Note
TheLayout
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 ofRow
andColumn
, 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 theadd(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 onLayoutSubelement
to make it easier to read the value.
See moreextension 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 } } }
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 moreDeclaration
Swift
public protocol SingleTraitLayout
-
Conforming types can calculate the size that they require within a layout.
See moreDeclaration
Swift
public protocol Measurable
-
Marker protocol used by generic extensions to native views (e.g.
See moreUIView
).Declaration
Swift
public protocol NativeView
-
Conform to this protocol to handle links tapped in an
AttributedLabel
.Use the
See moreURLHandlerEnvironmentKey
orEnvironment.urlHandler
property to override the link handler in the environment.Declaration
Swift
public protocol URLHandler