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:
| Parameter | Result 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:
| Type | Description |
|---|
AttributedString | Rich text for titles, subtitles, footnotes, captions |
TextOrIcon | A 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
Use ViewBuilder when…
Use type-based when…
- 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 are binding directly from a data model
- All fields are text, icons, or standard images
- You want Fiori default typography and layout without extra code
- You are populating a list or table with many items
// Populate from a model object
let item = workOrder
ObjectItem(
title: AttributedString(item.title),
subtitle: AttributedString(item.assetNumber),
footnote: AttributedString(item.location),
status: .text(AttributedString(item.priority)),
detailImage: Image(systemName: "wrench.adjustable")
)
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.