Screens
Every screen is a UIViewController you push onto your own navigation stack.
The factories are async (they read your settings), @MainActor, and each one
starts the SDK if you have not — so all of them can throw
storageUnavailable(reason:).
Each takes an onEvent closure and reports through it. Nothing is presented for
you.
properties
PropertyManagement, on tours.properties.
| Method | Returns |
|---|---|
makePropertyListViewController(subtitle:onEvent:) | The list of properties · PropertyListEvent |
makePropertyViewController(property:onEvent:) | One property's floors and rooms · PropertyEvent |
makeFloorViewController(floor:onEvent:) | One floor · FloorEvent |
makeRoomViewController(room:onEvent:) | One room · RoomEvent |
Plus four non-screen calls:
| Method | Purpose |
|---|---|
createProperty(name:floorCount:metadata:) | Create a property, returns a Property handle |
property(id:) | Look one up; nil if it no longer exists |
status(of:) | One-shot PropertyStatus |
statusUpdates(for:) | AsyncStream<PropertyStatus> |
let list = try await tours.properties.makePropertyListViewController(
subtitle: "Acme Ltd",
onEvent: { event in
switch event {
case .selectProperty(let property): show(property)
case .failed(let error): present(error)
}
}
)
subtitle is an optional line under the title.
structureCapture
StructureCapture, on tours.structureCapture. Builds the floor plan.
func makeViewController(
floor: Floor,
onEvent: (StructureCaptureEvent) -> Void
) async throws(NoughtyToursError) -> UIViewController
The flow owns its own sub-navigation — capture, then review — and pops itself
back on finished. You only handle cancelled and redoRequested:
switch event {
case .finished: break // the flow pops itself
case .cancelled: navigationController.popViewController(animated: true)
case .redoRequested: mapFloor(floor) // build a fresh flow, same floor
}
panoramaCapture
PanoramaCapture, on tours.panoramaCapture. Two overloads — capture into a
floor, or into a specific room.
func makeViewController(floor: Floor, onEvent: …) async throws(NoughtyToursError) -> UIViewController
func makeViewController(room: Room, onEvent: …) async throws(NoughtyToursError) -> UIViewController
finished reports what this visit added:
case .finished(let floor, let capturedInSession):
// `capturedInSession` counts this visit to the screen, not the floor's total.
log("captured \(capturedInSession) panoramas on \(floor.name ?? floor.id)")
case .cancelled:
// Backed out. Anything captured before that is kept.
They know whether a floor is "Ground floor" or "Floor 2". You own the stack — pushing, popping — and any bar-button items or title view you add on top.