You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Swift和SwiftUI中用Enum与static var管理AR状态是否符合最佳实践?

问题描述

我正在自学Swift,无前辈指导代码或提供学习帮助。为替代Bool类型,我定义了包含selfie和world两个case的ARSessionState枚举用于管理AR会话状态:

enum ARSessionState {
    case selfie
    case world
    
    mutating func toggle() {
        self = (self == .selfie) ? .world : .selfie
    }
    
    private static var selfieConfiguration: ARFaceTrackingConfiguration = {
        let configuration = ARFaceTrackingConfiguration()
        configuration.isWorldTrackingEnabled = true
        return configuration
    }()
    
    private static var worldConfiguration: ARWorldTrackingConfiguration = {
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal]
        configuration.userFaceTrackingEnabled = true
        return configuration
    }()

    var configuration: ARConfiguration {
        switch self {
        case .selfie:
            return ARSessionState.selfieConfiguration
        case .world:
            return ARSessionState.worldConfiguration
        }
    }
}

并在SwiftUI视图中通过@State属性包装器使用该枚举:

struct ContentView : View {
    @State private var session: ARSessionState = .world

    ...
    
    var body: some View {
        
        ZStack {
            
            ...
            
            Button(action: {session.toggle()} ) {

                Image(systemName: "arrow.triangle.2.circlepath.camera")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 50, height: 50)
            
                }.onChange(of: session) { newValue in
                let configuration = session.configuration
                
                ...

            }
        }
    }
}

我希望切换状态时自动加载对应ARConfiguration,因此在枚举中实现了mutating toggle方法、private static var配置属性及返回配置的computed property。现请教:

  1. 用此类双case Enum替代Bool是否为最佳实践?
  2. 在SwiftUI的@State变量中使用mutating方法修改状态是否合理?
  3. 在Enum中定义private static var属性是否合适?
  4. 通过computed property调用static属性是否符合规范?
    同时欢迎提供其他Swift编程最佳实践建议。

解答

1. 双case枚举替代Bool是否为最佳实践?

这不仅是合理做法,更是推荐的最佳实践。相比Bool的true/false,双case枚举的selfie/world具备明确的语义,任何人读代码都能立刻理解每个状态代表的含义,避免了Bool语义模糊的问题。另外,这种写法扩展性更强:如果以后需要新增AR会话状态(比如objectScanning),直接给枚举加新case即可,不需要重构原有Bool相关的逻辑,符合开闭原则。

2. 在SwiftUI的@State变量中使用mutating方法修改状态是否合理?

完全合理。@State包装的是值类型,而mutating方法正是Swift为值类型设计的、用于修改自身内部状态的语法。将状态切换逻辑封装在枚举的toggle()方法中,视图只需要调用这个方法即可,不需要关心具体的切换逻辑,符合单一职责原则。同时,SwiftUI会自动捕捉@State值的变化,触发视图更新,这种写法和直接赋值session = .selfie的效果一致,但封装性更好。

3. 在Enum中定义private static var属性是否合适?

非常合适。static属性属于枚举类型本身,在这里用来缓存预配置好的ARConfiguration对象,避免每次访问都重新创建实例,提升性能。用private修饰保证了这些配置对象的封装性,外部代码无法直接访问,只能通过枚举的configuration计算属性获取,符合封装的设计原则。而且配置和枚举状态强关联,放在枚举内部能让相关逻辑聚合在一起,代码更整洁。

4. 通过computed property调用static属性是否符合规范?

完全符合规范。计算属性的核心作用就是根据当前实例的状态返回对应的值,这里根据枚举的selfie/world case返回对应的静态配置对象,逻辑清晰、语义明确。外部代码只需要访问session.configuration就能拿到当前状态对应的配置,不需要关心内部的配置存储和获取逻辑,完美体现了封装的思想。


额外Swift编程最佳实践建议
  • 优化toggle方法可读性:当前的三元运算符写法可以换成switch语句,扩展性更好,以后新增case时更容易修改:
    mutating func toggle() {
        switch self {
        case .selfie: self = .world
        case .world: self = .selfie
        }
    }
    
  • 分离视图与业务逻辑:可以将AR会话的管理逻辑放到ViewModel中(用@Observable或ObservableObject),而不是直接在ContentView中处理。这样视图只负责UI展示和用户交互,ViewModel负责状态管理和AR会话的控制,符合MVVM架构,代码更易维护。
  • 添加设备兼容性检查:在初始化静态配置对象时,建议添加设备支持检查,比如判断当前设备是否支持面部追踪,避免运行时崩溃:
    private static var selfieConfiguration: ARFaceTrackingConfiguration? = {
        guard ARFaceTrackingConfiguration.isSupported else { return nil }
        let configuration = ARFaceTrackingConfiguration()
        configuration.isWorldTrackingEnabled = true
        return configuration
    }()
    
  • 在onChange中使用newValue:在onChange闭包里,直接使用参数newValue获取最新状态的配置,比访问session更准确,因为newValue就是触发回调的最新值:
    .onChange(of: session) { newValue in
        let configuration = newValue.configuration
        // 处理配置切换
    }
    
  • 考虑配置的可变性:如果需要在运行时动态修改配置参数(比如根据用户设置调整平面检测类型),可以将静态配置改为可修改的,或者提供方法重新生成配置,而不是一直使用初始化时的缓存。

内容的提问来源于stack exchange,提问作者D.Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:55:10