Skip to Content

iOS SDK

Integrate Graffity AR Cloud using GraffityARCloudConfiguration and the public GraffityARCloud session class. These docs describe the 5.1.1 API.

Requirements

  • An AR Cloud project and access token from Graffity Console.
  • iOS 18.0 or later on an ARKit world-tracking capable physical device. Test camera tracking and VPS on a device.
  • Xcode with the iOS 18 SDK or later and Swift 6 package tools support.
  • Network access for venue lookup, localization, assets, and maps.

Install the SDK

In Xcode, choose File → Add Package Dependencies, then enter:

https://github.com/Graffity-Technologies/graffity-arcloud-ios.git

Select 5.1.1 or a newer compatible 5.x release and add the GraffityARCloud library product to your app target. The package carries the binary framework and its dependencies. See Apple’s package installation guide .

Use import GraffityARCloud in your app’s Swift files.

Add permissions

Add both descriptions to your app target’s Info.plist, with wording appropriate for your app:

Info.plist
<key>NSCameraUsageDescription</key> <string>Use the camera to locate you and display AR content in the venue.</string> <key>NSLocationWhenInUseUsageDescription</key> <string>Use your location to find nearby venues and start AR navigation.</string>

The SDK requests when-in-use location authorization and camera access as needed when its view starts. Handle denied permissions through SDK errors. A seed location does not replace authorization.

Configure and initialize

Construct an immutable configuration, then initialize on the main actor with try:

import GraffityARCloud @MainActor func makeARSession(accessToken: String) throws -> GraffityARCloud { let configuration = GraffityARCloudConfiguration( accessToken: accessToken, mode: .arContent ) return try GraffityARCloud(configuration: configuration) }

Use .arContent to localize immediately and show AR content. The default, .navigation, opens a destination map first; selecting a destination starts localization and route guidance. The docked minimap is a separate opt-in with minimap: .enabled.

The configuration initializer does not throw. The SDK initializer checks the token’s basic format and throws GraffityARCloudError.invalidAccessToken for malformed input. Server authorization happens later and failures arrive through the delegate and state. See all configuration options.

Present the AR experience

Retain one SDK instance per logical session. AR starts when its hosted view appears; there is no public start() call.

ARExperienceViewController.swift
import UIKit import GraffityARCloud @MainActor final class ARExperienceViewController: UIViewController, @preconcurrency GraffityARCloudDelegate { private let sdk: GraffityARCloud private var arController: UIViewController? init(accessToken: String) throws { sdk = try GraffityARCloud(configuration: GraffityARCloudConfiguration( accessToken: accessToken, mode: .arContent )) super.init(nibName: nil, bundle: nil) sdk.delegate = self } required init?(coder: NSCoder) { fatalError("Use init(accessToken:)") } override func viewDidLoad() { super.viewDidLoad() let controller = sdk.makeViewController() arController = controller addChild(controller) controller.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(controller.view) NSLayoutConstraint.activate([ controller.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), controller.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), controller.view.topAnchor.constraint(equalTo: view.topAnchor), controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) controller.didMove(toParent: self) let closeButton = UIButton(type: .system) closeButton.setTitle("Close", for: .normal) closeButton.addTarget(self, action: #selector(closeExperience), for: .touchUpInside) closeButton.translatesAutoresizingMaskIntoConstraints = false view.addSubview(closeButton) NSLayoutConstraint.activate([ closeButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12), closeButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16) ]) } @objc private func closeExperience() { Task { await endSession() if let navigationController { navigationController.popViewController(animated: true) } else { dismiss(animated: true) } } } func graffityARCloud( _ sdk: GraffityARCloud, didFailWith error: GraffityARCloudError ) { // Route the message to your app's error UI. print(error.localizedDescription) } // Call before dismissing or popping this host at the end of the session. func endSession() async { await sdk.shutdown() arController?.willMove(toParent: nil) arController?.view.removeFromSuperview() arController?.removeFromParent() arController = nil } }

Create the host from your presenting controller and catch initialization failures:

@MainActor func presentAR(from presenter: UIViewController, accessToken: String) { do { let controller = try ARExperienceViewController(accessToken: accessToken) controller.modalPresentationStyle = .fullScreen presenter.present(controller, animated: true) } catch { print(error.localizedDescription) } }

Run on a device

Connect a supported device, choose it as the Xcode run destination, and run. Grant camera and location access. Scan the mapped venue and follow the camera guidance. In navigation mode, select a destination before scanning.

Use state.vpsState or didLocalizeIn to recognize localization. isSceneReady means the AR scene is running, not that VPS has found a section.

Continue with iOS options and the API reference. Report issues through the issue center.