The panorama of computing is present process a profound transformation with the emergence of spatial computing platforms(VR and AR). As we step into this new period, the intersection of digital actuality, Augmented Reality, and on-device machine studying presents unprecedented alternatives for builders to create experiences that seamlessly mix digital content material with the bodily world.
The introduction of visionOS marks a big milestone on this evolution. Apple’s Spatial Computing platform combines refined {hardware} capabilities with highly effective growth frameworks, enabling builders to construct functions that may perceive and work together with the bodily surroundings in actual time. This convergence of spatial consciousness and on-device machine studying capabilities opens up new potentialities for object recognition and monitoring functions that had been beforehand difficult to implement.
What We’re Constructing
On this information, we’ll be constructing an app that showcases the ability of on-device machine studying in visionOS. We’ll create an app that may acknowledge and observe a weight-reduction plan soda can in actual time, overlaying visible indicators and data instantly within the consumer’s subject of view.
Our app will leverage a number of key applied sciences within the visionOS ecosystem. When a consumer runs the app, they’re introduced with a window containing a rotating 3D mannequin of our goal object together with utilization directions. As they give the impression of being round their surroundings, the app repeatedly scans for weight-reduction plan soda cans. Upon detection, it shows dynamic bounding strains across the can and locations a floating textual content label above it, all whereas sustaining exact monitoring as the article or consumer strikes by area.
Earlier than we start growth, let’s guarantee we’ve got the mandatory instruments and understanding in place. This tutorial requires:
- The newest model of Xcode 16 with visionOS SDK put in
- visionOS 2.0 or later operating on an Apple Imaginative and prescient Professional machine
- Primary familiarity with SwiftUI and the Swift programming language
The event course of will take us by a number of key levels, from capturing a 3D mannequin of our goal object to implementing real-time monitoring and visualization. Every stage builds upon the earlier one, providing you with a radical understanding of creating options powered by on-device machine studying for visionOS.
Constructing the Basis: 3D Object Seize
Step one in creating our object recognition system entails capturing an in depth 3D mannequin of our goal object. Apple supplies a robust app for this function: RealityComposer, out there for iOS by the App Retailer.
When capturing a 3D mannequin, environmental circumstances play a vital position within the high quality of our outcomes. Organising the seize surroundings correctly ensures we get the absolute best knowledge for our machine studying mannequin. A well-lit area with constant lighting helps the seize system precisely detect the article’s options and dimensions. The weight-reduction plan soda can must be positioned on a floor with good distinction, making it simpler for the system to tell apart the article’s boundaries.
The seize course of begins by launching the RealityComposer app and deciding on “Object Seize” from the out there choices. The app guides us by positioning a bounding field round our goal object. This bounding field is important because it defines the spatial boundaries of our seize quantity.

As soon as we’ve captured all the small print of the soda can with the assistance of the in-app information and processed the photographs, a .usdz file containing our 3D mannequin might be created. This file format is particularly designed for AR/VR functions and accommodates not simply the visible illustration of our object, but in addition essential data that might be used within the coaching course of.
Coaching the Reference Mannequin
With our 3D mannequin in hand, we transfer to the following essential part: coaching our recognition mannequin utilizing Create ML. Apple’s Create ML software supplies an easy interface for coaching machine studying fashions, together with specialised templates for spatial computing functions.
To start the coaching course of, we launch Create ML and choose the “Object Monitoring” template from the spatial class. This template is particularly designed for coaching fashions that may acknowledge and observe objects in three-dimensional area.

After creating a brand new venture, we import our .usdz file into Create ML. The system mechanically analyzes the 3D mannequin and extracts key options that might be used for recognition. The interface supplies choices for configuring how our object must be acknowledged in area, together with viewing angles and monitoring preferences.
When you’ve imported the 3d mannequin and analyzed it in varied angles, go forward and click on on “Practice”. Create ML will course of our mannequin and start the coaching part. Throughout this part, the system learns to acknowledge our object from varied angles and below totally different circumstances. The coaching course of can take a number of hours because the system builds a complete understanding of our object’s traits.

The output of this coaching course of is a .referenceobject file, which accommodates the skilled mannequin knowledge optimized for real-time object detection in visionOS. This file encapsulates all of the realized options and recognition parameters that may allow our app to establish weight-reduction plan soda cans within the consumer’s surroundings.
The profitable creation of our reference object marks an essential milestone in our growth course of. We now have a skilled mannequin able to recognizing our goal object in real-time, setting the stage for implementing the precise detection and visualization performance in our visionOS software.
Preliminary Venture Setup
Now that we’ve got our skilled reference object, let’s arrange our visionOS venture. Launch Xcode and choose “Create a brand new Xcode venture”. Within the template selector, select visionOS below the platforms filter and choose “App”. This template supplies the essential construction wanted for a visionOS software.

Within the venture configuration dialog, configure your venture with these main settings:
- Product Title: SodaTracker
- Preliminary Scene: Window
- Immersive House Renderer: RealityKit
- Immersive House: Combined
After venture creation, we have to make a couple of important modifications. First, delete the file named ToggleImmersiveSpaceButton.swift as we received’t be utilizing it in our implementation.
Subsequent, we’ll add our beforehand created belongings to the venture. In Xcode’s Venture Navigator, find the “RealityKitContent.rkassets” folder and add the 3D object file (“SodaModel.usdz” file). This 3D mannequin might be utilized in our informative view. Create a brand new group named “ReferenceObjects” and add the “Food regimen Soda.referenceobject” file we generated utilizing Create ML.
The ultimate setup step is to configure the mandatory permission for object monitoring. Open your venture’s Data.plist file and add a brand new key: NSWorldSensingUsageDescription. Set its worth to “Used to trace weight-reduction plan sodas”. This permission is required for the app to detect and observe objects within the consumer’s surroundings.
With these setup steps full, we’ve got a correctly configured visionOS venture prepared for implementing our object monitoring performance.
Entry Level Implementation
Let’s begin with SodaTrackerApp.swift, which was mechanically created once we arrange our visionOS venture. We have to modify this file to assist our object monitoring performance. Exchange the default implementation with the next code:
import SwiftUI
/**
SodaTrackerApp is the principle entry level for the appliance.
It configures the app's window and immersive area, and manages
the initialization of object detection capabilities.
The app mechanically launches into an immersive expertise
the place customers can see Food regimen Soda cans being detected and highlighted
of their surroundings.
*/
@most important
struct SodaTrackerApp: App {
/// Shared mannequin that manages object detection state
@StateObject non-public var appModel = AppModel()
/// System surroundings worth for launching immersive experiences
@Atmosphere(.openImmersiveSpace) var openImmersiveSpace
var physique: some Scene {
WindowGroup {
ContentView()
.environmentObject(appModel)
.job {
// Load and put together object detection capabilities
await appModel.initializeDetector()
}
.onAppear {
Job {
// Launch instantly into immersive expertise
await openImmersiveSpace(id: appModel.immersiveSpaceID)
}
}
}
.windowStyle(.plain)
.windowResizability(.contentSize)
// Configure the immersive area for object detection
ImmersiveSpace(id: appModel.immersiveSpaceID) {
ImmersiveView()
.surroundings(appModel)
}
// Use combined immersion to mix digital content material with actuality
.immersionStyle(choice: .fixed(.combined), in: .combined)
// Conceal system UI for a extra immersive expertise
.persistentSystemOverlays(.hidden)
}
}
The important thing side of this implementation is the initialization and administration of our object detection system. When the app launches, we initialize our AppModel which handles the ARKit session and object monitoring setup. The initialization sequence is essential:
.job {
await appModel.initializeDetector()
}
This asynchronous initialization hundreds our skilled reference object and prepares the ARKit session for object monitoring. We guarantee this occurs earlier than opening the immersive area the place the precise detection will happen.
The immersive area configuration is especially essential for object monitoring:
.immersionStyle(choice: .fixed(.combined), in: .combined)
The combined immersion type is crucial for our object monitoring implementation because it permits RealityKit to mix our visible indicators (bounding bins and labels) with the real-world surroundings the place we’re detecting objects. This creates a seamless expertise the place digital content material precisely aligns with bodily objects within the consumer’s area.
With these modifications to SodaTrackerApp.swift, our app is able to start the article detection course of, with ARKit, RealityKit, and our skilled mannequin working collectively within the combined actuality surroundings. Within the subsequent part, we’ll study the core object detection performance in AppModel.swift, one other file that was created throughout venture setup.
Core Detection Mannequin Implementation
AppModel.swift, created throughout venture setup, serves as our core detection system. This file manages the ARKit session, hundreds our skilled mannequin, and coordinates the article monitoring course of. Let’s study its implementation:
import SwiftUI
import RealityKit
import ARKit
/**
AppModel serves because the core mannequin for the soda can detection software.
It manages the ARKit session, handles object monitoring initialization,
and maintains the state of object detection all through the app's lifecycle.
This mannequin is designed to work with visionOS's object monitoring capabilities,
particularly optimized for detecting Food regimen Soda cans within the consumer's surroundings.
*/
@MainActor
@Observable
class AppModel: ObservableObject {
/// Distinctive identifier for the immersive area the place object detection happens
let immersiveSpaceID = "SodaTracking"
/// ARKit session occasion that manages the core monitoring performance
/// This session coordinates with visionOS to course of spatial knowledge
non-public var arSession = ARKitSession()
/// Devoted supplier that handles the real-time monitoring of soda cans
/// This maintains the state of at the moment tracked objects
non-public var sodaTracker: ObjectTrackingProvider?
/// Assortment of reference objects used for detection
/// These objects comprise the skilled mannequin knowledge for recognizing soda cans
non-public var targetObjects: [ReferenceObject] = []
/**
Initializes the article detection system by loading and getting ready
the reference object (Food regimen Soda can) from the app bundle.
This methodology hundreds a pre-trained mannequin that accommodates spatial and
visible details about the Food regimen Soda can we need to detect.
*/
func initializeDetector() async {
guard let objectURL = Bundle.most important.url(forResource: "Food regimen Soda", withExtension: "referenceobject") else {
print("Error: Did not find reference object in bundle - guarantee Food regimen Soda.referenceobject exists")
return
}
do {
let referenceObject = strive await ReferenceObject(from: objectURL)
self.targetObjects = [referenceObject]
} catch {
print("Error: Did not initialize reference object: (error)")
}
}
/**
Begins the lively object detection course of utilizing ARKit.
This methodology initializes the monitoring supplier with loaded reference objects
and begins the real-time detection course of within the consumer's surroundings.
Returns: An ObjectTrackingProvider if efficiently initialized, nil in any other case
*/
func beginDetection() async -> ObjectTrackingProvider? {
guard !targetObjects.isEmpty else { return nil }
let tracker = ObjectTrackingProvider(referenceObjects: targetObjects)
do {
strive await arSession.run([tracker])
self.sodaTracker = tracker
return tracker
} catch {
print("Error: Did not initialize monitoring: (error)")
return nil
}
}
/**
Terminates the article detection course of.
This methodology safely stops the ARKit session and cleans up
monitoring sources when object detection is now not wanted.
*/
func endDetection() {
arSession.cease()
}
}
On the core of our implementation is ARKitSession, visionOS’s gateway to spatial computing capabilities. The @MainActor attribute ensures our object detection operations run on the principle thread, which is essential for synchronizing with the rendering pipeline.
non-public var arSession = ARKitSession()
non-public var sodaTracker: ObjectTrackingProvider?
non-public var targetObjects: [ReferenceObject] = []
The ObjectTrackingProvider is a specialised element in visionOS that handles real-time object detection. It really works along side ReferenceObject cases, which comprise the spatial and visible data from our skilled mannequin. We keep these as non-public properties to make sure correct lifecycle administration.
The initialization course of is especially essential:
let referenceObject = strive await ReferenceObject(from: objectURL)
self.targetObjects = [referenceObject]
Right here, we load our skilled mannequin (the .referenceobject file we created in Create ML) right into a ReferenceObject occasion. This course of is asynchronous as a result of the system must parse and put together the mannequin knowledge for real-time detection.
The beginDetection methodology units up the precise monitoring course of:
let tracker = ObjectTrackingProvider(referenceObjects: targetObjects)
strive await arSession.run([tracker])
After we create the ObjectTrackingProvider, we cross in our reference objects. The supplier makes use of these to ascertain the detection parameters — what to search for, what options to match, and how one can observe the article in 3D area. The ARKitSession.run name prompts the monitoring system, starting the real-time evaluation of the consumer’s surroundings.
Immersive Expertise Implementation
ImmersiveView.swift, supplied in our preliminary venture setup, manages the real-time object detection visualization within the consumer’s area. This view processes the continual stream of detection knowledge and creates visible representations of detected objects. Right here’s the implementation:
import SwiftUI
import RealityKit
import ARKit
/**
ImmersiveView is chargeable for creating and managing the augmented actuality
expertise the place object detection happens. This view handles the real-time
visualization of detected soda cans within the consumer's surroundings.
It maintains a set of visible representations for every detected object
and updates them in real-time as objects are detected, moved, or eliminated
from view.
*/
struct ImmersiveView: View {
/// Entry to the app's shared mannequin for object detection performance
@Atmosphere(AppModel.self) non-public var appModel
/// Root entity that serves because the guardian for all AR content material
/// This entity supplies a constant coordinate area for all visualizations
@State non-public var sceneRoot = Entity()
/// Maps distinctive object identifiers to their visible representations
/// Permits environment friendly updating of particular object visualizations
@State non-public var activeVisualizations: [UUID: ObjectVisualization] = [:]
var physique: some View {
RealityView { content material in
// Initialize the AR scene with our root entity
content material.add(sceneRoot)
Job {
// Start object detection and observe modifications
let detector = await appModel.beginDetection()
guard let detector else { return }
// Course of real-time updates for object detection
for await replace in detector.anchorUpdates {
let anchor = replace.anchor
let id = anchor.id
swap replace.occasion {
case .added:
// Object newly detected - create and add visualization
let visualization = ObjectVisualization(for: anchor)
activeVisualizations[id] = visualization
sceneRoot.addChild(visualization.entity)
case .up to date:
// Object moved - replace its place and orientation
activeVisualizations[id]?.refreshTracking(with: anchor)
case .eliminated:
// Object now not seen - take away its visualization
activeVisualizations[id]?.entity.removeFromParent()
activeVisualizations.removeValue(forKey: id)
}
}
}
}
.onDisappear {
// Clear up AR sources when view is dismissed
cleanupVisualizations()
}
}
/**
Removes all lively visualizations and stops object detection.
This ensures correct cleanup of AR sources when the view is now not lively.
*/
non-public func cleanupVisualizations() {
for (_, visualization) in activeVisualizations {
visualization.entity.removeFromParent()
}
activeVisualizations.removeAll()
appModel.endDetection()
}
}
The core of our object monitoring visualization lies within the detector’s anchorUpdates stream. This ARKit characteristic supplies a steady move of object detection occasions:
for await replace in detector.anchorUpdates {
let anchor = replace.anchor
let id = anchor.id
swap replace.occasion {
case .added:
// Object first detected
case .up to date:
// Object place modified
case .eliminated:
// Object now not seen
}
}
Every ObjectAnchor accommodates essential spatial knowledge concerning the detected soda can, together with its place, orientation, and bounding field in 3D area. When a brand new object is detected (.added occasion), we create a visualization that RealityKit will render within the appropriate place relative to the bodily object. As the article or consumer strikes, the .up to date occasions guarantee our digital content material stays completely aligned with the actual world.
Visible Suggestions System
Create a brand new file named ObjectVisualization.swift for dealing with the visible illustration of detected objects. This element is chargeable for creating and managing the bounding field and textual content overlay that seems round detected soda cans:
import RealityKit
import ARKit
import UIKit
import SwiftUI
/**
ObjectVisualization manages the visible components that seem when a soda can is detected.
This class handles each the 3D textual content label that seems above the article and the
bounding field that outlines the detected object in area.
*/
@MainActor
class ObjectVisualization {
/// Root entity that accommodates all visible components
var entity: Entity
/// Entity particularly for the bounding field visualization
non-public var boundingBox: Entity
/// Width of bounding field strains - 0.003 supplies optimum visibility with out being too intrusive
non-public let outlineWidth: Float = 0.003
init(for anchor: ObjectAnchor) {
entity = Entity()
boundingBox = Entity()
// Arrange the principle entity's rework primarily based on the detected object's place
entity.rework = Remodel(matrix: anchor.originFromAnchorTransform)
entity.isEnabled = anchor.isTracked
createFloatingLabel(for: anchor)
setupBoundingBox(for: anchor)
refreshBoundingBoxGeometry(with: anchor)
}
/**
Creates a floating textual content label that hovers above the detected object.
The textual content makes use of Avenir Subsequent font for optimum readability in AR area and
is positioned barely above the article for clear visibility.
*/
non-public func createFloatingLabel(for anchor: ObjectAnchor) {
// 0.06 items supplies optimum textual content measurement for viewing at typical distances
let labelSize: Float = 0.06
// Use Avenir Subsequent for its readability and trendy look in AR
let font = MeshResource.Font(identify: "Avenir Subsequent", measurement: CGFloat(labelSize))!
let textMesh = MeshResource.generateText("Food regimen Soda",
extrusionDepth: labelSize * 0.15,
font: font)
// Create a cloth that makes textual content clearly seen towards any background
var textMaterial = UnlitMaterial()
textMaterial.shade = .init(tint: .orange)
let textEntity = ModelEntity(mesh: textMesh, supplies: [textMaterial])
// Place textual content above object with sufficient clearance to keep away from intersection
textEntity.rework.translation = SIMD3(
anchor.boundingBox.middle.x - textMesh.bounds.max.x / 2,
anchor.boundingBox.extent.y + labelSize * 1.5,
0
)
entity.addChild(textEntity)
}
/**
Creates a bounding field visualization that outlines the detected object.
Makes use of a magenta shade transparency to offer a transparent
however non-distracting visible boundary across the detected soda can.
*/
non-public func setupBoundingBox(for anchor: ObjectAnchor) {
let boxMesh = MeshResource.generateBox(measurement: [1.0, 1.0, 1.0])
// Create a single materials for all edges with magenta shade
let boundsMaterial = UnlitMaterial(shade: .magenta.withAlphaComponent(0.4))
// Create all edges with uniform look
for _ in 0..
The bounding field creation is a key side of our visualization. Moderately than utilizing a single field mesh, we assemble 12 particular person edges that kind a wireframe define. This method supplies higher visible readability and permits for extra exact management over the looks. The perimeters are positioned utilizing SIMD3 vectors for environment friendly spatial calculations:
edge.place = [
extent.x / 2 * (index % 2 == 0 ? -1 : 1),
extent.y / 2 * (index
This mathematical positioning ensures each edge aligns perfectly with the detected object’s dimensions. The calculation uses the object’s extent (width, height, depth) and creates a symmetrical arrangement around its center point.
This visualization system works in conjunction with our ImmersiveView to create real-time visual feedback. As the ImmersiveView receives position updates from ARKit, it calls refreshTracking on our visualization, which updates the transform matrices to maintain precise alignment between the virtual overlays and the physical object.
Informative View

ContentView.swift, provided in our project template, handles the informational interface for our app. Here’s the implementation:
import SwiftUI
import RealityKit
import RealityKitContent
/**
ContentView provides the main window interface for the application.
Displays a rotating 3D model of the target object (Diet Soda can)
along with clear instructions for users on how to use the detection feature.
*/
struct ContentView: View {
// State to control the continuous rotation animation
@State private var rotation: Double = 0
var body: some View {
VStack(spacing: 30) {
// 3D model display with rotation animation
Model3D(named: "SodaModel", bundle: realityKitContentBundle)
.padding(.vertical, 20)
.frame(width: 200, height: 200)
.rotation3DEffect(
.degrees(rotation),
axis: (x: 0, y: 1, z: 0)
)
.onAppear {
// Create continuous rotation animation
withAnimation(.linear(duration: 5.0).repeatForever(autoreverses: true)) {
rotation = 180
}
}
// Instructions for users
VStack(spacing: 15) {
Text("Diet Soda Detection")
.font(.title)
.fontWeight(.bold)
Text("Hold your diet soda can in front of you to see it automatically detected and highlighted in your space.")
.font(.body)
.multilineTextAlignment(.center)
.foregroundColor(.secondary)
.padding(.horizontal)
}
}
.padding()
.frame(maxWidth: 400)
}
}
This implementation displays our 3D-scanned soda model (SodaModel.usdz) with a rotating animation, providing users with a clear reference of what the system is looking for. The rotation helps users understand how to present the object for optimal detection.
With these components in place, our application now provides a complete object detection experience. The system uses our trained model to recognize diet soda cans, creates precise visual indicators in real-time, and provides clear user guidance through the informational interface.
Conclusion

In this tutorial, we’ve built a complete object detection system for visionOS that showcases the integration of several powerful technologies. Starting from 3D object capture, through ML model training in Create ML, to real-time detection using ARKit and RealityKit, we’ve created an app that seamlessly detects and tracks objects in the user’s space.
This implementation represents just the beginning of what’s possible with on-device machine learning in spatial computing. As hardware continues to evolve with more powerful Neural Engines and dedicated ML accelerators and frameworks like Core ML mature, we’ll see increasingly sophisticated applications that can understand and interact with our physical world in real-time. The combination of spatial computing and on-device ML opens up possibilities for applications ranging from advanced AR experiences to intelligent environmental understanding, all while maintaining user privacy and low latency.
Supply hyperlink