Вопрос или проблема
Я использую следующий код на iOS 18, и он вызывает у меня проблемы, что ModelEntity.loadAsync теперь устарел. Есть идеи, как исправить эту проблему?
import ARKit
import RealityKit
import Combine
class Coordinator: NSObject, ARSessionDelegate {
weak var view: ARView?
var cancellable: AnyCancellable?
@objc func handleTap(_ recognizer: UITapGestureRecognizer) {
guard let view = self.view else { return }
let tapLocation = recognizer.location(in: view)
let results = view.raycast(from: tapLocation, allowing: .estimatedPlane, alignment: .horizontal)
if let result = results.first {
// создаем анкорный объект
let anchor = AnchorEntity(raycastResult: result)
cancellable = ModelEntity.load(named: "shoe")
.sink { loadCompletion in
if case let .failure(error) = loadCompletion {
print("Не удалось загрузить модель \(error)")
}
self.cancellable?.cancel()
} receiveValue: { entity in
anchor.addChild(entity)
}
view.scene.addAnchor(anchor)
}
}
}
Ответ или решение
Согласно обновлениям iOS 18, метод ModelEntity.loadAsync
был объявлен устаревшим, что может вызвать проблемы в вашем коде, использующем этот метод для загрузки 3D моделей в приложениях с использованием ARKit и RealityKit. В этой статье мы рассмотрим, как обновить ваш код для работы с новыми методами, предоставляемыми RealityKit, и как правильно обрабатывать загрузку моделей.
Обновление кода
Для начала, нам необходимо заменить устаревший метод loadAsync
на новый подход с использованием ModelEntity.load(contentsOf:)
или ModelEntity.load(named:)
, если вы загружаете модель из локального ресурса. Более того, следует учитывать, что асинхронная загрузка запускается иначе, рекомендуется использовать Task
для работы с async/await
.
Вот обновленная версия вашего кода с учетом этих изменений:
import ARKit
import RealityKit
import Combine
class Coordinator: NSObject, ARSessionDelegate {
weak var view: ARView?
@objc func handleTap(_ recognizer: UITapGestureRecognizer) {
guard let view = self.view else { return }
let tapLocation = recognizer.location(in: view)
let results = view.raycast(from: tapLocation, allowing: .estimatedPlane, alignment: .horizontal)
if let result = results.first {
// Создаём якорь для сущности
let anchor = AnchorEntity(raycastResult: result)
// Загрузка 3D модели
Task {
do {
let entity = try await ModelEntity.load(named: "shoe")
anchor.addChild(entity)
view.scene.addAnchor(anchor)
} catch {
print("Не удалось загрузить модель: \(error)")
}
}
}
}
}
Пояснения к коду
-
Использование
Task
иasync/await
:- Загрузка 3D модели теперь происходит в асинхронном контексте, что улучшает читаемость кода и позволяет обрабатывать ошибки более удобно через
do-catch
. Это также соответствует современным парадигмам программирования на Swift, делая ваш код более эффективным и поддерживаемым.
- Загрузка 3D модели теперь происходит в асинхронном контексте, что улучшает читаемость кода и позволяет обрабатывать ошибки более удобно через
-
Оптимизация под нативные методы:
- Зависимости от устаревших методов и классов сведены к минимуму, что улучшает совместимость вашего кода с будущими версиями iOS.
-
Обработка ошибок:
- Теперь ошибки при загрузке модели обрабатываются с использованием
catch
, что позволяет локализовать проблемы и упрощает отладку.
- Теперь ошибки при загрузке модели обрабатываются с использованием
Заключение
Обновление вашего кода в соответствии с новыми стандартами iOS позволяет избежать проблем, связанных с устаревшими методами. Используя async/await
, вы не только упрощаете обработку асинхронных операций, но и улучшаете общую структуру вашего приложения. Это особенно актуально для разработчиков, стремящихся к созданию высококачественного пользовательского опыта в приложениях дополненной реальности.
Для соблюдения лучших практик рекомендую следить за обновлениями документации Apple для своевременного внедрения новых возможностей и избегания устаревших подходов.