Skip to main content

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.

MethodReturns
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:

MethodPurpose
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.
The screens title themselves

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.