ARKit для Swift: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

ARKit для Swift: Полное руководство по дополненной реальности

1. Что это и зачем нужна

ARKit — это фреймворк дополненной реальности (AR), разработанный компанией Apple для платформ iOS и iPadOS. Он позволяет разработчикам создавать захватывающие AR-приложения, которые накладывают виртуальные 3D-объекты, анимации и информацию на реальный мир, снятый камерой устройства. ARKit использует технологии компьютерного зрения, обработки данных с датчиков (акселерометр, гироскоп, камера) и машинного обучения для точного отслеживания положения устройства в пространстве, обнаружения плоскостей (столы, пол, стены) и распознавания изображений и объектов.

Зачем нужен ARKit? Он открывает безграничные возможности для самых разных сфер: от игр (Pokémon GO) и образования (интерактивные учебники) до розничной торговли (примерка мебели в IKEA Place) и промышленности (визуализация сложных механизмов). Вместо того чтобы писать сложные алгоритмы компьютерного зрения с нуля, разработчик получает готовый, оптимизированный и мощный инструмент, который берет на себя всю "тяжелую работу" по анализу видеопотока и отслеживанию.

В этой статье мы подробно разберем, как начать работу с ARKit на языке Swift, рассмотрим его основные классы и методы, а также напишем полноценный пример приложения. Вы узнаете, как быстро добавить AR-функциональность в ваш проект и избежать типичных ошибок.

2. Установка

ARKit — это не сторонняя библиотека, а встроенный фреймворк Apple. Его не нужно устанавливать через менеджеры пакетов (CocoaPods, Swift Package Manager) или pip. Для его использования достаточно импортировать его в ваш Xcode проект.

Важное замечание: ARKit работает только на устройствах с процессором A9 и выше (iPhone 6s и новее, iPad 2017 и новее) и требует iOS 11.0 или новее. Для симулятора Xcode поддержка ARKit ограничена (не работает камера), поэтому для полноценной разработки и тестирования необходимо физическое устройство.

Шаги для начала работы:

  1. Откройте Xcode и создайте новый проект (File → New → Project).
  2. Выберите шаблон "Augmented Reality App". Xcode автоматически настроит проект с использованием SceneKit (или RealityKit) и ARKit.
  3. Если вы добавляете ARKit в существующий проект, просто импортируйте фреймворк в нужный файл.

Команда для импорта (в коде):

import ARKit

Больше никаких команд установки не требуется. Если вы используете RealityKit (более современный фреймворк для AR), импортируйте его:

import RealityKit

3. Быстрый старт — минимальный рабочий пример

Давайте создадим минимальное AR-приложение, которое отобразит простой 3D-куб на обнаруженной горизонтальной плоскости.

1. Настройка ViewController:

Убедитесь, что ваш ViewController наследуется от ARSCNViewDelegate (для SceneKit) или ARViewDelegate (для RealityKit). В этом примере мы используем SceneKit, так как он более прост для понимания основ.

import UIKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.showsStatistics = true // Показывает FPS и другую статистику
        sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints] // Показывает точки, которые видит камера
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal] // Включаем обнаружение горизонтальных плоскостей
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        sceneView.session.pause() // Останавливаем сессию, когда приложение уходит на фон
    }
}

2. Добавление объекта при обнаружении плоскости:

Реализуем метод делегата renderer(_:didAdd:for:), который вызывается, когда ARKit находит новую плоскость.

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    // 1. Проверяем, что это плоскость
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    // 2. Создаем геометрию плоскости (визуализация найденной поверхности)
    let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
    let planeNode = SCNNode(geometry: plane)
    planeNode.position = SCNVector3(planeAnchor.center.x, 0, planeAnchor.center.z)
    planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0) // Поворачиваем плоскость

    // 3. Добавляем куб на эту плоскость
    let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    let boxNode = SCNNode(geometry: box)
    boxNode.position = SCNVector3(0, 0.05, 0) // Поднимаем куб на половину его высоты

    // 4. Добавляем узлы в сцену
    planeNode.addChildNode(boxNode)
    node.addChildNode(planeNode)
}

Этот минимальный пример показывает, как запустить AR-сессию, обнаружить плоскость и разместить на ней 3D-объект. Запустите приложение на реальном устройстве и наведите камеру на стол или пол — вы увидите куб.

4. Основные методы/функции/классы

Рассмотрим 8 ключевых классов и методов ARKit, которые вам понадобятся в 90% проектов.

4.1. ARSession

Сигнатура: class ARSession

Что делает: Это центральный объект, управляющий всем процессом AR. Он принимает конфигурацию, запускает и останавливает обработку данных с камеры и датчиков, а также управляет всеми обнаруженными якорями (ARAnchor).

Пример:

let session = ARSession()
let configuration = ARWorldTrackingConfiguration()
session.run(configuration)
// ... через какое-то время
session.pause()

4.2. ARWorldTrackingConfiguration

Сигнатура: class ARWorldTrackingConfiguration

Что делает: Основная конфигурация для отслеживания мира. Она использует визуально-инерциальную одометрию (VIO) для точного отслеживания положения устройства в 6 степенях свободы (6 DOF: перемещение и поворот). Позволяет настроить обнаружение плоскостей, распознавание изображений и объектов.

Пример:

let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical] // Ищем и горизонтальные, и вертикальные плоскости
configuration.environmentTexturing = .automatic // Автоматическое текстурирование окружения для реалистичного освещения
sceneView.session.run(configuration)

4.3. ARAnchor и ARPlaneAnchor

Сигнатура: class ARAnchor / class ARPlaneAnchor: ARAnchor

Что делает: ARAnchor — это базовая точка в пространстве, к которой можно "привязать" виртуальный объект. ARPlaneAnchor — это подкласс, представляющий обнаруженную плоскость (пол, стол, стена). Он содержит информацию о положении, размере (extent) и центре (center) плоскости.

Пример:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    if let planeAnchor = anchor as? ARPlaneAnchor {
        print("Обнаружена плоскость шириной \(planeAnchor.extent.x) и высотой \(planeAnchor.extent.z)")
        // Создаем визуальный узел для плоскости
    }
}

4.4. ARSCNViewDelegate

Сигнатура: protocol ARSCNViewDelegate

Что делает: Протокол делегата для ARSCNView. Предоставляет методы для обработки событий жизненного цикла AR-сессии и управления узлами SceneKit, которые соответствуют якорям. Ключевые методы: renderer(_:didAdd:for:), renderer(_:didUpdate:for:), renderer(_:didRemove:for:).

Пример:

class ViewController: UIViewController, ARSCNViewDelegate {
    // ... реализация методов делегата
    func session(_ session: ARSession, didFailWithError error: Error) {
        print("Ошибка сессии: \(error.localizedDescription)")
    }
    func sessionWasInterrupted(_ session: ARSession) {
        print("Сессия прервана")
    }
    func sessionInterruptionEnded(_ session: ARSession) {
        print("Сессия возобновлена")
    }
}

4.5. SCNScene и SCNNode

Сигнатура: class SCNScene / class SCNNode

Что делает: SCNScene — это корневой контейнер для всей 3D-сцены. SCNNode — это узел в графе сцены. Каждый узел может содержать геометрию (SCNGeometry), источники света, камеры и другие узлы (дочерние). Именно через узлы вы размещаете и перемещаете объекты в AR-пространстве.

Пример:

// Создаем сферу
let sphere = SCNSphere(radius: 0.05)
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = SCNVector3(0, 0.1, -0.5) // 50 см перед камерой, 10 см вверх

// Добавляем в корневую сцену
sceneView.scene.rootNode.addChildNode(sphereNode)

4.6. ARHitTestResult (Устарел в iOS 14, используйте raycast)

Сигнатура: class ARHitTestResult / func raycastQuery(from:allowing:alignment:)

Что делает: Позволяет определить, на какой объект реального мира (или существующий якорь) указывает точка на экране. Это основа для взаимодействия пользователя с AR-миром (например, касание экрана для размещения объекта). Начиная с iOS 14, Apple рекомендует использовать ARRaycastQuery вместо hit-test.

Пример (с использованием raycast):

@IBAction func handleTap(_ gesture: UITapGestureRecognizer) {
    let tapLocation = gesture.location(in: sceneView)
    guard let query = sceneView.raycastQuery(from: tapLocation, allowing: .existingPlaneGeometry, alignment: .horizontal) else { return }
    let results = sceneView.session.raycast(query)
    if let firstResult = results.first {
        let transform = firstResult.worldTransform
        let position = SCNVector3(transform.columns.3.x, transform.columns.3.y, transform.columns.3.z)
        // Размещаем объект в этой позиции
        let boxNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0))
        boxNode.position = position
        sceneView.scene.rootNode.addChildNode(boxNode)
    }
}

4.7. ARImageAnchor и ARReferenceImage

Сигнатура: class ARImageAnchor: ARAnchor / class ARReferenceImage

Что делает: Позволяет распознавать заранее заданные 2D-изображения (логотипы, постеры, картины) в реальном мире. Когда изображение распознано, создается ARImageAnchor, к которому можно привязать виртуальный контент (например, анимацию поверх журнала).

Пример:

// В конфигурации
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
configuration.detectionImages = referenceImages

// В делегате
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    print("Обнаружено изображение: \(imageAnchor.referenceImage.name ?? "unknown")")
    // Добавляем 3D-текст поверх изображения
    let textNode = SCNNode(geometry: SCNText(string: "Hello AR!", extrusionDepth: 0.1))
    textNode.position = SCNVector3(0, 0.1, 0)
    node.addChildNode(textNode)
}

4.8. ARSCNDebugOptions

Сигнатура: struct ARSCNDebugOptions

Что делает: Набор опций для визуальной отладки AR-сессии. Позволяет отображать на экране "фиче-поинты" (ключевые точки, которые видит камера), мировые оси координат, сетки обнаруженных плоскостей и другую отладочную информацию. Незаменимо при разработке для понимания того, что "видит" ARKit.

Пример:

sceneView.debugOptions = [
    .showFeaturePoints,          // Показывает желтые точки
    .showWorldOrigin,            // Показывает оси X, Y, Z в начале координат
    .showAnchorOrigins,          // Показывает оси для каждого якоря
    .showAnchorGeometry          // Показывает геометрию якорей (например, плоскости)
]

Рекомендаций