> For the complete documentation index, see [llms.txt](https://multiset.gitbook.io/multiset/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://multiset.gitbook.io/multiset/native-sdk/ios-swift-native/api-reference/multisetcallback.md).

# MultiSetCallback

## Overview

`MultiSetCallback` is the protocol your app implements to receive SDK events: authentication, localization, object tracking, and mesh loading. The instance is passed to `MultiSet.shared.initialize(config:callback:)` and is held weakly by the SDK.

```swift
class MultiSetSDKDelegate: MultiSetCallback {
    func onSDKReady() { }
    func onAuthenticationSuccess() { }
    func onAuthenticationFailure(error: String) { }
    func onLocalizationSuccess(result: LocalizationResult) { }
    func onLocalizationFailure(error: String) { }
    func onTrackingStateChanged(state: TrackingState) { }
}
```

Only the six methods above are required. Every other method has a default no-op implementation, so existing integrations keep compiling when new callbacks are added.

***

## Required Methods

### onSDKReady()

Called synchronously from `initialize(config:callback:)`, before authentication starts.

This is not an authentication signal. Wait for `onAuthenticationSuccess()` before calling `localize()`. Attaching an `ARSession` here is safe, because the SDK applies it once authenticated.

### onAuthenticationSuccess()

Authentication with the MultiSet servers succeeded. The SDK is ready to localize.

### onAuthenticationFailure(error: String)

Authentication failed.

| Parameter | Type     | Description                |
| --------- | -------- | -------------------------- |
| `error`   | `String` | Description of the failure |

### onLocalizationSuccess(result: LocalizationResult)

A pose was returned and accepted. The gizmo has moved and, if `meshVisualization` is enabled, the mesh is loading.

| Parameter | Type                 | Description                                                                                         |
| --------- | -------------------- | --------------------------------------------------------------------------------------------------- |
| `result`  | `LocalizationResult` | See [LocalizationResult](/multiset/native-sdk/ios-swift-native/api-reference/localizationresult.md) |

### onLocalizationFailure(error: String)

The localization request failed, or no pose was found.

| Parameter | Type     | Description                |
| --------- | -------- | -------------------------- |
| `error`   | `String` | Description of the failure |

When `firstLocalizationUntilSuccess` is enabled, failures before the first success are retried silently and do not reach this callback.

### onTrackingStateChanged(state: TrackingState)

ARKit tracking state changed.

| Parameter | Type            | Description                          |
| --------- | --------------- | ------------------------------------ |
| `state`   | `TrackingState` | `.tracking`, `.paused` or `.stopped` |

***

## Optional Methods

Each of these has a default empty implementation.

### onLocalizationFalsePositive(info: FalsePositiveInfo)

The server returned a pose, but it contradicts the device's own AR trajectory, so the SDK discarded it. This fires **instead of** `onLocalizationSuccess`, and only when [`poseConsistencyCheck`](/multiset/native-sdk/ios-swift-native/api-reference/multisetconfig.md#pose-consistency-settings) is enabled.

The request itself succeeded. The answer was wrong, most likely because the query image matched a visually similar part of the space. The AR scene is left untouched: the gizmo and mesh keep the last accepted pose.

| Parameter | Type                | Description                                  |
| --------- | ------------------- | -------------------------------------------- |
| `info`    | `FalsePositiveInfo` | Details of the discarded response, see below |

```swift
func onLocalizationFalsePositive(info: FalsePositiveInfo) {
    print("Discarded: \(info.summary)")

    if info.consecutiveCount >= 3 {
        // Repeated rejections from one spot usually mean the user should move,
        // or that the reference itself is stale.
        showResetPrompt()
    }
}
```

There is no automatic fast retry after a false positive, because a retry from the same spot tends to produce the same wrong match. Prompt the user to move to a more distinctive viewpoint and localize again. If they insist the rejections are wrong, call `MultiSet.shared.resetPoseConsistencyReference()`, which makes the next result trusted and adopted as the new reference.

### onMeshLoaded(mapCode: String)

A map mesh finished downloading and rendering.

| Parameter | Type     | Description                           |
| --------- | -------- | ------------------------------------- |
| `mapCode` | `String` | Code of the map whose mesh was loaded |

### onMeshLoadError(error: String)

Mesh download or rendering failed. Localization itself is unaffected.

### onObjectTrackingSuccess(objectCode: String, confidence: Double)

A tracked object was located and its outline mesh placed.

| Parameter    | Type     | Description                       |
| ------------ | -------- | --------------------------------- |
| `objectCode` | `String` | Code of the detected object       |
| `confidence` | `Double` | Detection confidence (0.0 to 1.0) |

### onObjectTrackingFailure(error: String)

Object tracking failed or no object was matched.

### onObjectMeshLoaded(objectCode: String)

An object mesh was loaded and rendered with the outline shader.

***

## FalsePositiveInfo

Details of a localization response that the pose consistency check discarded.

| Property           | Type       | Description                                                                              |
| ------------------ | ---------- | ---------------------------------------------------------------------------------------- |
| `jumpMeters`       | `Float`    | How far the discarded response placed the map from where the last accepted fix placed it |
| `thresholdMeters`  | `Float`    | The tolerance that was in force, from `poseConsistencyThreshold`                         |
| `consecutiveCount` | `Int`      | Consecutive false positives since the last accepted fix. `1` on the first one            |
| `mapCodes`         | `[String]` | Map codes the server reported for the discarded response                                 |
| `confidence`       | `Float?`   | Server confidence of the discarded response, when reported                               |
| `reason`           | `String`   | Short machine-readable explanation, for logs                                             |
| `summary`          | `String`   | One-line description of all of the above, ready to log                                   |

A high `confidence` on a discarded response is normal and is the point of the check. The server was sure about a match that the device's own motion rules out.

***

## Related

* [MultiSetConfig](/multiset/native-sdk/ios-swift-native/api-reference/multisetconfig.md)
* [LocalizationResult](/multiset/native-sdk/ios-swift-native/api-reference/localizationresult.md)
* [LandingView](/multiset/native-sdk/ios-swift-native/sample-views/landingview.md)
* [ARLocalizationView](/multiset/native-sdk/ios-swift-native/sample-views/arlocalizationview.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://multiset.gitbook.io/multiset/native-sdk/ios-swift-native/api-reference/multisetcallback.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
