WWDC Quick Look 💓 By SwiftGGTeam
Explore enhancements to your spatial business app

Explore enhancements to your spatial business app

观看原视频

Highlight

visionOS 26 把 UVC 视频与 Neural Engine 访问开放给所有开发者,并新增 Window Follow Mode、共享坐标空间、内容防截屏与 Camera Region 四类企业 API。

核心内容

去年 visionOS 首次为企业客户开放底层能力,但代价并不小:要拿 UVC 摄像头视频,得申请 managed entitlement、配许可证文件,连 Neural Engine 都得走企业流程。一个想用 USB 摄像头做远程诊断的小团队,光是审批就要走完整套企业开发者合规流程。

visionOS 26 把这条线松开了。Apple 工程师 Alex Powers 在 session 里宣布,UVC 视频访问和 Neural Engine 访问今年全员可用,不再需要企业许可证或 entitlement。对象跟踪从只能在 CreateML app 里点点点,扩展到命令行训练,可以直接接进 CI 管线。许可证管理也搬到了 Apple Developer 账户里,续期通过 OTA 推送给设备。

剩下的企业级能力分成两条线:用户体验侧,多了 Window Follow Mode(窗口跟人走)、SharedCoordinateSpaceProvider(同房间多台 Vision Pro 对齐坐标系)、contentCaptureProtected(敏感内容自动从录屏/共享中遮蔽)。环境可视化侧,Camera Frame Provider 能拿左右单独摄像头或立体声,新增的 Camera Region API 可以把现实世界一小块区域单独抠出来放大、增强对比度,做远程仪表读数这类场景。

详细内容

命令行训练对象跟踪模型(03:00

xcrun createml objecttracker -s my.usdz -o my.referenceobject

关键点:

  • xcrun createml objecttracker:调用 CreateML 的对象跟踪子命令,与 GUI 版的 CreateML app 共享同一套训练参数。
  • -s my.usdz:输入的 USDZ 模型文件,用来生成对象的 reference object。
  • -o my.referenceobject:输出资产路径,可以直接接进自动化流水线,按文件批处理。

VisionEntitlementServices 检查许可状态(04:28

import VisionEntitlementServices

func checkLicenseStatus() {
    let license = EnterpriseLicenseDetails.shared

    guard license.licenseStatus == .valid else {
        print("Enterprise license is not valid: \(license.licenseStatus)")
        return
    }

    if license.isApproved(for: .mainCameraAccess) {
        print("Main Camera Access approved. Enabling feature...")
    } else {
        print("Main Camera Access not approved.")
    }
}

关键点:

  • EnterpriseLicenseDetails.shared:单例,封装当前 app 的许可证信息,包括状态和过期时间。
  • licenseStatus == .valid:先确认整体许可证有效,避免在已过期的许可证上继续走企业逻辑。
  • isApproved(for: .mainCameraAccess):按 entitlement 粒度判断是否被授权使用某项企业 API,运行时动态决定是否开启功能。
  • 该框架还支持 Increased Performance Headroom 的 entitlement 校验,在跑高负载任务前先确认权限。

SharedCoordinateSpaceProvider 自定义共享空间(10:04

import ARKit

class SharedCoordinateSpaceModel {
    let arkitSession = ARKitSession()
    let sharedCoordinateSpace = SharedCoordinateSpaceProvider()
    let worldTracking = WorldTrackingProvider()

    func runARKitSession() async {
        do {
            try await arkitSession.run([sharedCoordinateSpace, worldTracking])
        } catch {
            reportError("Error: running session: \(error)")
        }
    }

    func pushCoordinateSpaceData(_ data: Data) {
        if let coordinateSpaceData = SharedCoordinateSpaceProvider.CoordinateSpaceData(data: data) {
            sharedCoordinateSpace.push(data: coordinateSpaceData)
        }
    }

    func pollCoordinateSpaceData() async {
        if let coordinateSpaceData = sharedCoordinateSpace.nextCoordinateSpaceData {
            // Send my coordinate space data
        }
    }

    func addWorldAnchor(at transform: simd_float4x4) async throws {
        let anchor = WorldAnchor(originFromAnchorTransform: transform, sharedWithNearbyParticipants: true)
        try await worldTracking.addAnchor(anchor)
    }
}

关键点:

  • SharedCoordinateSpaceProviderWorldTrackingProvider 一起跑在 ARKitSession 上,复用熟悉的 ARKit data provider 模型。
  • nextCoordinateSpaceData:拉取本机要广播给其他参与者的对齐数据,由开发者自己决定走 TCP/UDP/自有协议。
  • push(data:):把从其他设备网络收到的 CoordinateSpaceData 喂回 ARKit,用以建立共同坐标系。
  • WorldAnchor(... sharedWithNearbyParticipants: true):给锚点加上共享标记,房间内其他 Vision Pro 看到同一锚点位置一致。
  • eventUpdates 异步序列会在参与者加入/离开、共享开关切换时通知 app(10:04)。

contentCaptureProtected 阻止敏感内容外泄(12:50

struct SecretDocumentView: View {
    var body: some View {
        VStack {
            Text("Secrets")
                .font(.largeTitle)
                .padding()

            SensitiveDataView()
                .contentCaptureProtected()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
    }
}

关键点:

  • contentCaptureProtected() 是 SwiftUI view modifier,需要 protected content entitlement。
  • 加在哪一层,哪一层就在系统截屏、录屏、Screen Mirroring、SharePlay 中被自动遮蔽。
  • 戴着 Vision Pro 的本人仍能看到原始内容,外部观众看到的是模糊或遮挡块。
  • 也支持包住整个 RealityKit 场景,不只是 2D 视图。

Camera Region 把现实抠一块出来(16:48 / 21:15

import SwiftUI
import VisionKit

struct InspectorView: View {
    @Environment(CameraFeedDelivery.self) private var cameraFeedDelivery: CameraFeedDelivery

    var body: some View {
        CameraRegionView(isContrastAndVibrancyEnhancementEnabled: true) { result in
            var pixelBuffer: CVReadOnlyPixelBuffer?
            switch result {
            case .success(let value):
                pixelBuffer = value.pixelBuffer
            case .failure(let error):
                reportError("Failure: \(error.localizedDescription)")
                cameraFeedDelivery.stopFeed()
                return nil
            }

            cameraFeedDelivery.frameUpdate(pixelBuffer: pixelBuffer!)
            return nil
        }
    }
}

关键点:

  • CameraRegionView 来自 VisionKit,是高层封装,把窗口当成「指向现实世界一块区域」的取景器。
  • isContrastAndVibrancyEnhancementEnabled: true:开启对比度与色彩增强,适合远处仪表盘、指针读数。
  • 闭包里收到 pixelBuffer,可送到自己的视频管线(远程协助、OCR、推流)做后续处理。
  • 底层 ARKit 等价物是 CameraRegionAnchor(originFromAnchorTransform:width:height:cameraEnhancement:),可指定 .stabilization 等增强模式,并通过 cameraRegionProvider.anchorUpdates(forID:) 拿到逐帧像素更新。
  • Apple 建议单个 CameraRegionAnchor 占可见区域不超过六分之一,否则资源消耗会显著增加。

核心启发

  • 把 USB 摄像头玩出花:UVC 视频访问今年向所有开发者开放,不再需要企业许可证。

    • 为什么值得做:之前被许可证劝退的团队现在可以直接接入工业相机、热成像、显微镜等专业设备。
    • 怎么开始:拿到 Vision Pro Developer Strap,按 Building spatial experiences for business apps 文档接入 UVC API,先打通最简单的 webcam 视频流再加业务逻辑。
  • 用命令行批量训练对象跟踪模型xcrun createml objecttracker 让模型训练可以脚本化。

    • 为什么值得做:原本一个产品 SKU 一个 USDZ 一次手动点击,现在可以写一个 shell 脚本跑完几十个对象,CI 里自动产出 referenceobject。
    • 怎么开始:参考 Implementing object tracking in your app,在 CI 容器里安装 Xcode command line tools,把 USDZ 输入与 referenceobject 输出接进 artifact 流程。
  • 给敏感视图统一加上 contentCaptureProtected():一行 modifier 控制截屏/录屏/共享行为。

    • 为什么值得做:金融、医疗、设计稿等场景做合规时,最大的痛点是「员工无意中开了 SharePlay/录屏」。这个 API 把控制收归到 SwiftUI 视图层。
    • 怎么开始:先列出所有展示敏感数据的子视图,统一封装一个 SensitiveContent wrapper,内部加 .contentCaptureProtected(),并在企业开发者后台申请 protected content entitlement。
  • 本地网络的多人 Vision Pro 协作:用 SharedCoordinateSpaceProvider 在自有网络上跑共享坐标空间。

    • 为什么值得做:SharePlay 走 iCloud 太重,工厂、医院这类内网封闭场景需要完全本地的协作通道。新 ARKit API 把网络层完全交给开发者。
    • 怎么开始:在 ARKitSession 里同时启动 SharedCoordinateSpaceProviderWorldTrackingProvider,用 Bonjour + UDP 在局域网里双向交换 CoordinateSpaceData,再加共享 WorldAnchor。

关联 Session

评论

GitHub Issues · utterances