Skip to main content
Every component in FioriSwiftUICore ships with two distinct initializer families. Choosing the right one depends on how much control you need over sub-component rendering.

ViewBuilder (ResultBuilder) initializer

The ViewBuilder initializer accepts @ViewBuilder closures for each field. This gives you unrestricted control over what each field renders — any View is valid, including images, custom layouts, or other Fiori components. Each optional field defaults to { EmptyView() }, so you only supply closures for the fields you need.
ObjectItem(
    title: {
        Text("Rouja Pakiman")
    },
    description: {
        Text("Rouja has worked for the company for ten years and has all of the skills " +
             "that would be necessary for developing quality applications. " +
             "She is proficient in Java as well as CSS, Bootstrap, and Swift.")
    },
    status: {
        Text("Available")
    },
    detailImage: {
        Image("person_square4")
            .resizable()
            .frame(width: 45, height: 45)
            .clipShape(Circle())
    }
)
Specialised result builders are used for collection fields:
ParameterResult builder
icons@IconBuilder
avatars@AvatarsBuilder
footnoteIcons@FootnoteIconsBuilder
tags@TagBuilder
This means you can place multiple Image or Tag views directly inside the closure and the SDK assembles them into the correct stack layout automatically.

Type-based initializer

The type-based initializer accepts plain Swift value types. The SDK wraps each value in the appropriate default view, giving you the Fiori-standard appearance with minimal code.
ObjectItem(
    title: "Transformer Overheating When After Being on for 1 Hour or Longer",
    subtitle: "Three Phase Pad Mounted Transformer (533423)",
    footnote: "1000 - Hamburg, MECHANIK",
    description: "Customer noticed that the transformer started to over heat within 45 minutes " +
                 "each time he turned it on at 7:30am. The first technician who looked at this " +
                 "did not have the correct additional tools to complete the job.",
    status: TextOrIcon.text("High"),
    detailImage: Image(systemName: "person"),
    icons: [
        TextOrIcon.text("1"),
        TextOrIcon.icon(Image(systemName: "circle.fill")),
        TextOrIcon.icon(Image(systemName: "mail"))
    ]
)
Key types used in type-based initializers:
TypeDescription
AttributedStringRich text for titles, subtitles, footnotes, captions
TextOrIconA value that is either .text(AttributedString), .icon(Image), or .both(AttributedString, Image)
Image?Optional image for detailImage and similar single-image fields
[TextOrIcon]Array of text-or-icon values for icons, avatars, footnoteIcons
[AttributedString]Array of attributed strings for tags
FioriButton?Optional button for action

Choosing between the two

  • A field must display a non-text view (image, custom layout, progress view)
  • You need to compose multiple views inside one field
  • You want to conditionally show or hide a sub-view
  • You are building a one-off UI that does not need data binding
// Title shows a company logo image instead of text
ObjectItem {
    Image("CompanyLogo")
        .resizable()
        .frame(width: 120, height: 32)
} status: {
    HStack(spacing: 4) {
        Circle()
            .fill(.green)
            .frame(width: 8, height: 8)
        Text("Online")
    }
}
You can mix both approaches in the same view hierarchy. For example, use the type-based initializer for most fields and supply a @ViewBuilder closure via the modifier-based sub-component styling APIs for the fields that need custom rendering.

Build docs developers (and LLMs) love