Post

Replies

Boosts

Views

Activity

Reply to SCNScene.write(to:) for usdz export only works for first call
The behavior is caused by two separate issues with a SwiftUI Sandboxed app: First, the SCNScene needs to be rendered in order to export correctly. You can't do what I was doing (create a bunch of nodes, stuff them into the scene's root node and call scene.write) and get a correctly rendered usdz. It must first be put on screen in a SwiftUI SceneView, which causes a lot of other initialization to occur. I suppose you could instantiate a SCNRenderer and call prepare() on the root node, but that has some extra complications. Second, the Sandbox prevents a direct export to a URL provided by .fileExporter(). This is because Scene.write() works in two steps: it first creates a .usdc export, and zips the resulting files into a single .usdz. The intermediate files don't have the write privileges the URL provided by .fileExporter() does (assuming you've set the Sandbox "User Selected File" privilege to "Read/Write"), so Scene.write() fails, even if the target URL is writeable, if the target directory is outside the Sandbox. My solution was to write a custom FileWrapper, which I return if the WriteConfiguration UTType is .usdz: public class USDZExportFileWrapper: FileWrapper { var exportScene: SCNScene public init(scene: SCNScene) { exportScene = scene super.init(regularFileWithContents: Data()) } required init?(coder inCoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override public func write(to url: URL, options: FileWrapper.WritingOptions = [], originalContentsURL: URL?) throws { let tempFilePath = NSTemporaryDirectory() + UUID().uuidString + ".usdz" let tempURL = URL(fileURLWithPath: tempFilePath) exportScene.write(to: tempURL, delegate: nil) try FileManager.default.moveItem(at: tempURL, to: url) } } Usage in a ReferenceFileDocument: public func fileWrapper(snapshot: Data, configuration: WriteConfiguration) throws -> FileWrapper { if configuration.contentType == .usdz { return USDZExportFileWrapper(scene: scene) } return .init(regularFileWithContents: snapshot) }
Apr ’22
Reply to Unable to set initial selection state of SwiftUI `List` in iOS 14
I just got this to work in my app by making the selection variable non-optional, e.g. @State var selection: NavigationItem = .view1 Now the sidebar list shows up with the correct item highlighted. The initial state provided in the declaration can be overridden in the onAppear view modifier, i.e. .onAppear { selection = .view2 } Not sure this works if a nil selection state is a required option. Perhaps provide a .none enum case, and don't embed it in the list?
Dec ’22
Reply to ObjectCapture API & Sample broken with iOS17 & Xcode beta 5
For me too - crashed with SIGABRT on launch, console output: dyld[3234]: Symbol not found: _$s19_RealityKit_SwiftUI20ObjectCaptureSessionC7Combine010ObservableE0AAMc Referenced from: <294EDA13-E14C-3BFF-B705-8368778FF69F> /private/var/containers/Bundle/Application/255DCE73-DCDD-489F-8A6F-83DA8E04026C/GuidedCapture.app/GuidedCapture Expected in: <6A96F77C-1BEB-3925-B370-266184BF844F> /System/Library/Frameworks/_RealityKit_SwiftUI.framework/_RealityKit_SwiftUI
Jul ’23
Reply to How to attach point cloud(or depth data) to heic?
This just started happening to us in iOS 18. I noticed that HEIC files produced by the Object Capture API didn't have this problem, and it turns out the AVDepthData returned with AVCapturePhoto is in a disparity format, and needs to be converted to a depth format before retrieving it as a dictionary. I created an extension that handles this: import Foundation extension OSType { fileprivate func fourCCToString() -> String { let utf16 = [ UInt16((self >> 24) & 0xFF), UInt16((self >> 16) & 0xFF), UInt16((self >> 8) & 0xFF), UInt16((self & 0xFF)), ] return String(utf16CodeUnits: utf16, count: 4) } } extension AVDepthData { public func formattedForPhotogrammetry() -> AVDepthData { if depthDataType == kCVPixelFormatType_DepthFloat32 { return self } else if canCovertToDepthFloat32() { print( "converting \(depthDataType.fourCCToString()) to \(kCVPixelFormatType_DepthFloat32.fourCCToString())" ) return self.converting( toDepthDataType: kCVPixelFormatType_DepthFloat32) } else { return self } } public func canCovertToDepthFloat32() -> Bool { return availableDepthDataTypes.contains(kCVPixelFormatType_DepthFloat32) } } Now you can add this to an image destination, and get the Data() to write to a file: import CoreImage import Foundation extension CGImageDestination { func addImage(from imageSource: CGImageSource) { CGImageDestinationAddImageFromSource(self, imageSource, 0, nil) } func addDepthData(from depthData: AVDepthData) { guard var depthDictionary = depthData.formattedForPhotogrammetry() .dictionaryRepresentation( forAuxiliaryDataType: nil) else { return } // looking at images from ObjectCaptureSession, depth metadata isn't supplied, // so no sense in including it ourselves depthDictionary.removeValue(forKey: kCGImageAuxiliaryDataInfoMetadata) CGImageDestinationAddAuxiliaryDataInfo( self, kCGImageAuxiliaryDataTypeDepth, depthDictionary as CFDictionary) } func finalize() -> Bool { CGImageDestinationFinalize(self) } } Hope this helps.
Oct ’24
Reply to Using MPSession sendResource Progress in a SwiftUI ProgressView causes crash
After some further communication with DTS (Thanks Paris!), a workaround is to use XXViewRepresentable to wrap a platform-specific progress view. Here is my solution: import SwiftUI #if os(macOS) import AppKit public typealias SuperClass = NSViewRepresentable #else import UIKit public typealias SuperClass = UIViewRepresentable #endif public struct RepresentedProgressView: SuperClass { @State public private(set) var progress: Progress public init(_ progress: Progress) { self.progress = progress } #if os(macOS) public func makeNSView(context: Self.Context) -> NSProgressIndicator { let view = NSProgressIndicator() view.observedProgress = progress return view } public func updateNSView(_ uiView: Self.NSViewType, context: Self.Context) { } #else public func makeUIView(context: Self.Context) -> UIProgressView { let view = UIProgressView() view.observedProgress = progress return view } public func updateUIView(_ uiView: Self.UIViewType, context: Self.Context) { } #endif } This is working in our code, and doesn't crash with > 60 files transferred
4d