Post

Replies

Boosts

Views

Activity

SwiftUI app outputting CVDisplayLink related messages to console?
I'm getting a lot of output on the console as I run a MacOS based SwiftUI app I'm developing, for example: 2021-12-08 12:40:14.439565+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830820] CVCGDisplayLink::setCurrentDisplay: 1892262333 2021-12-08 12:40:14.439785+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830800] CVDisplayLinkCreateWithCGDisplays count: 1 [displayID[0]: 0x70c9a1bd] [CVCGDisplayLink: 0x7fe6e7830820] 2021-12-08 12:40:14.439827+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830800] CVDisplayLinkStart 2021-12-08 12:40:14.439853+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830820] CVDisplayLink::start 2021-12-08 12:40:14.439993+0000 SpDriveApp[6801:182706] [] [0x60000f698460] CVXTime::reset Has anyone else seen this? Have I accidentally switched on a diagnostic tool, or is there something else I am doing wrong?
11
0
3.8k
Apr ’22
Suppressing verbose console output - SwiftUI / MacOS Monterey
Is there anyway to suppress the very verbose console output I am getting with MacOS Monterey and SwiftUI code? Here's a snippet of the output: 2021-07-20 09:58:18.267602+0100 BBCFTEST[19341:1880374] IMKInputSession (deactivate) CFRunLoopObserver kCFRunLoopExit (State change BEGIN) - innerRunLoopCount=1, otherInnerRunLoopDetected=0 2021-07-20 09:58:18.267637+0100 BBCFTEST[19341:1880374] IMKInputSession (deactivate) CFRunLoopObserver kCFRunLoopExit (State change END) - innerRunLoopCount=0, otherInnerRunLoopDetected=0 2021-07-20 09:58:18.270063+0100 BBCFTEST[19341:1880374] IMKInputSession (deactivate) CFRunLoopRunInMode exited, (kCFRunLoopRunStopped) 2021-07-20 09:58:18.270109+0100 BBCFTEST[19341:1880374] IMKInputSession (deactivate) CFRunLoopRunInMode (kIMKXPCPrivateRunLoopMode) ] RunLoopFinished(1)/Stopped(2) - Run result = 2, (Invocation already done = 1) (Sentinel IsZombie = 0) 2021-07-20 09:58:18.270147+0100 BBCFTEST[19341:1880374] IMKInputSession (deactivate) CFRunLoopRunInMode() LOOP DONE!
7
0
2.4k
Aug ’21
MainActor.run failing to run closure when called from within a detached task
I have encountered an issue when trying to update the status of a detached task, by passing a closure to MainActor.run. To illustrate the issue consider a function that counts the number of files in a folder and its sub-directories. It runs in a Task.detached closure, as I don't want it blocking the main thread. Every 10,000th file it updates a Published property fileCount, by passing a closure to MainThread.run. However, the UI is failing to update and even giving me a spinning beach ball. The only way to stop this is by inserting await Task.sleep(1_000_000_000) before the call to MainThread.run. Here's the code: final class NewFileCounter: ObservableObject { @Published var fileCount = 0 func findImagesInFolder(_ folderURL: URL) { let fileManager = FileManager.default Task.detached { var foundFileCount = 0 let options = FileManager.DirectoryEnumerationOptions(arrayLiteral: [.skipsHiddenFiles, .skipsPackageDescendants]) if let enumerator = fileManager.enumerator(at: folderURL, includingPropertiesForKeys: [], options: options) { while let _ = enumerator.nextObject() as? URL { foundFileCount += 1 if foundFileCount % 10_000 == 0 { let fileCount = foundFileCount await Task.sleep(1_000_000_000) // <-- Only works with this in...comment out to see failure await MainActor.run { self.fileCount = fileCount } } } let fileCount = foundFileCount await MainActor.run { self.fileCount = fileCount } } } } } The code works if I revert to the old way of achieving this: final class OldFileCounter: ObservableObject { @Published var fileCount = 0 func findImagesInFolder(_ folderURL: URL) { let fileManager = FileManager.default DispatchQueue.global(qos: .userInitiated).async { let options = FileManager.DirectoryEnumerationOptions(arrayLiteral: [.skipsHiddenFiles, .skipsPackageDescendants]) var foundFileCount = 0 if let enumerator = fileManager.enumerator(at: folderURL, includingPropertiesForKeys: [], options: options) { while let _ = enumerator.nextObject() as? URL { foundFileCount += 1 if foundFileCount % 10_000 == 0 { let fileCount = foundFileCount DispatchQueue.main.async { self.fileCount = fileCount } } } let fileCount = foundFileCount DispatchQueue.main.async { self.fileCount = fileCount } } } } } What am I doing wrong? BTW - if you want to try out this code, here is a test harness. Be sure to pick a folder with lots of files in it and its sub-folders. import SwiftUI @main struct TestFileCounterApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var showPickerOld = false @StateObject private var fileListerOld = OldFileCounter() @State private var showPickerNew = false @StateObject private var fileListerNew = NewFileCounter() var body: some View { VStack { Button("Select folder to count files using DispatchQueue...") { showPickerOld = true } Text("\(fileListerOld.fileCount)").foregroundColor(.green) .fileImporter(isPresented: $showPickerOld, allowedContentTypes: [.folder], onCompletion: processOldSelectedURL ) Divider() Button("Select folder to count files using Swift 5.5 concurrency...") { showPickerNew = true } Text("\(fileListerNew.fileCount)").foregroundColor(.green) .fileImporter(isPresented: $showPickerNew, allowedContentTypes: [.folder], onCompletion: processNewSelectedURL ) } .frame(width: 400, height: 130) } private func processOldSelectedURL(_ result: Result<URL, Error>) { switch result { case .success(let url): fileListerOld.findImagesInFolder(url) case .failure: return } } private func processNewSelectedURL(_ result: Result<URL, Error>) { switch result { case .success(let url): fileListerNew.findImagesInFolder(url) case .failure: return } } }```
7
0
3.3k
Sep ’21
Accessing an actor's isolated state from within a SwiftUI view
I'm trying to understand a design pattern for accessing the isolated state held in an actor type from within a SwiftUI view. Take this naive code: actor Model: ObservableObject { @Published var num: Int = 0 func updateNumber(_ newNum: Int) { self.num = newNum } } struct ContentView: View { @StateObject var model = Model() var body: some View { Text("\(model.num)") // <-- Compiler error: Actor-isolated property 'num' can not be referenced from the main actor Button("Update number") { Task.detached() { await model.updateNumber(1) } } } } Understandably I get the compiler error Actor-isolated property 'num' can not be referenced from the main actor when I try and access the isolated value. Yet I can't understand how to display this data in a view. I wonder if I need a ViewModel that observes the actor, and updates itself on the main thread, but get compile time error Actor-isolated property '$num' can not be referenced from a non-isolated context. class ViewModel: ObservableObject { let model: Model @Published var num: Int let cancellable: AnyCancellable init() { let model = Model() self.model = model self.num = 0 self.cancellable = model.$num // <-- compile time error `Actor-isolated property '$num' can not be referenced from a non-isolated context` .receive(on: DispatchQueue.main) .sink { self.num = $0 } } } Secondly, imagine if this code did compile, then I would get another error when clicking the button that the interface is not being updated on the main thread...again I'm not sure how to effect this from within the actor?
3
2
9.7k
Apr ’25
Running FileManager.default.enumerator on different tasks
I'm writing a function where a directory and its descendants are scanned to produce a list of files. The function is part of a class, FileScanner. Here's a simplified version of the function: func scanFolder(_ folderURL: URL) async { // Set up configuration for directory search, varies based on need to search sub directories let resourceKeysArray: [URLResourceKey] = [.nameKey, .isDirectoryKey, .fileResourceTypeKey, .creationDateKey, .contentModificationDateKey, .contentTypeKey] let resourceKeysSet = Set&lt;URLResourceKey&gt;(resourceKeysArray) let options = FileManager.DirectoryEnumerationOptions(arrayLiteral: [.skipsHiddenFiles, .skipsPackageDescendants]) if let enumerator = FileManager.default.enumerator(at: folderURL, includingPropertiesForKeys: resourceKeysArray, options: options) { await folderScanStatus.markRunning() while await !folderScanStatus.cancelled, let fileURL = enumerator.nextObject() as? URL { print("\(id) found \(fileURL.path)") // Logging for debug purposes foundFiles.append(fileURL) } } } The code is async, as it has to call some async functions (I've left a couple in for illustration.) The user can have multiple scans in process simultaneously. For each one a new FileScanner is created, and de-inited once the scan has completed - the results are copied across elsewhere. scanFolder is called from within a Task: Task { await scanFolder(someURL) } I am finding that if two of these processes run at once, they can actually interfere with each other - i.e. one can scan the directory of the other. I added some logging to highlight the issue. The log line shows the ID of the scanner, and the file it has found. In this run there were two scanners: EDF43558-608E-47A4-81E5-97B9707B1D0F, scanning /Volumes/Back-up A/ 982EC712-D79E-4785-A1BA-3B53F85967F0, scanning /Users/TEST/ And here's some extracts from the log showing them working as expected: 982EC712-D79E-4785-A1BA-3B53F85967F0 found /Users/TEST/Files/R_24_04-04.txt EDF43558-608E-47A4-81E5-97B9707B1D0F found /Volumes/Back-up A/180704f01.txt And here's an example showing Scanner 982EC712-D79E-4785-A1BA-3B53F85967F0 finding a file that the other one also picked up: 982EC712-D79E-4785-A1BA-3B53F85967F0 found /Volumes/Back-up A/19839f92.txt : EDF43558-608E-47A4-81E5-97B9707B1D0F found /Volumes/Back-up A/19839f92.txt Any ideas why this is happening? I was under the impression FileManager was thread safe?
3
0
2.2k
Nov ’21
How to make an entity move in a RealityView so that collisions can be detected
I'm trying to detect when two entities collide. The following code shows a very basic set-up. How do I get the upperSphere to move? If I set its physicsBody.mode to .dynamic it moves with gravity (and the collision is reported), but when in kinematic mode it doesn't respond to the impulse: struct CollisionView: View { @State var subscriptions: [EventSubscription] = [] var body: some View { RealityView { content in let upperSphere = ModelEntity(mesh: .generateSphere(radius: 0.04)) let lowerSphere = ModelEntity(mesh: .generateSphere(radius: 0.04)) upperSphere.position = [0, 2, -2] upperSphere.physicsBody = .init() upperSphere.physicsBody?.mode = .kinematic upperSphere.physicsMotion = PhysicsMotionComponent() upperSphere.generateCollisionShapes(recursive: false) lowerSphere.position = [0, 1, -2] lowerSphere.physicsBody = .init() lowerSphere.physicsBody?.mode = .static lowerSphere.generateCollisionShapes(recursive: false) let sub = content.subscribe(to: CollisionEvents.Began.self, on: nil) { _ in print("Collision!") } subscriptions.append(sub) content.add(upperSphere) content.add(lowerSphere) Task { try? await Task.sleep(for: .seconds(2)) print("Impulse applied") upperSphere.applyLinearImpulse([0, -1, 0], relativeTo: nil) } } } }
3
0
1.2k
May ’24
Creating and applying a shader to change an entity's rendering in RealityKit
Hello, I am looking to create a shader to update an entity's rendering. As a basic example say I want to recolour an entity, but leave its original textures showing through: I understand with VisionOS I need to use Reality Composer Pro to create the shader, but I'm lost as how to reference the original colour that I'm trying to update in the node graph. All my attempts appear to completely override the textures in the entity (and its sub-entities) that I want to impact. Also the tutorials / examples I've looked at appear to create materials, not add an effect on top of existing materials. Any hints or pointers? Assuming this is possible, I've been trying to load the material in code, and apply to an entity. But do I need to do this to all child entities, or just the topmost? do { let entity = MyAssets.createModelEntity(.plane) // Loads from bundle and performs config let material = try await ShaderGraphMaterial(named: "/Root/TestMaterial", from: "Test", in: realityKitContentBundle) entity.applyToChildren { $0.components[ModelComponent.self]?.materials = [material] } root.addChild(entity) } catch { fatalError(error.localizedDescription) }
3
0
928
Oct ’24
Cannot find XXXXX in scope errors for UnitTests - Xcode 12.2 beta 3
I'm unable to compile my project for UnitTests at present - get a load of Cannot Find XXXXX in Scope errors. Anybody else getting this, or ideas of how to resolve. I've tried cleaning the build folder, restarting Xcode, checking my unit test code file is only a member of the test target. Code compiles for the debug and production builds.
2
0
2.8k
Jan ’21
GCControllerDidConnect notification not received in VisionOS 2.0
I am unable to get VisionOS 2.0 (simulator) to receive the GCControllerDidConnect notification and thus am unable to setup support for a gamepad. However, it works in VisionOS 1.2. For VisionOS 2.0 I've tried adding: .handlesGameControllerEvents(matching: .gamepad) attribute to the view Supports Controller User Interaction to Info.plist Supported game controller types -> Extended Gamepad to Info.plist ...but the notification still doesn't fire. It does when the code is run from VisionOS 1.2 simulator, both of which have the Send Game Controller To Device option enabled. Here is the example code. It's based on the Xcode project template. The only files updated were ImmersiveView.swift and Info.plist, as detailed above: import SwiftUI import GameController import RealityKit import RealityKitContent struct ImmersiveView: View { var body: some View { RealityView { content in // Add the initial RealityKit content if let immersiveContentEntity = try? await Entity(named: "Immersive", in: realityKitContentBundle) { content.add(immersiveContentEntity) } NotificationCenter.default.addObserver( forName: NSNotification.Name.GCControllerDidConnect, object: nil, queue: nil) { _ in print("Handling GCControllerDidConnect notification") } } .modify { if #available(visionOS 2.0, *) { $0.handlesGameControllerEvents(matching: .gamepad) } else { $0 } } } } extension View { func modify<T: View>(@ViewBuilder _ modifier: (Self) -> T) -> some View { return modifier(self) } }
2
1
938
Dec ’24
EntityAction implementation example
Does anyone have experience of creating their own EntityActions? Say for example I wanted one that faded up the opacity of an entity, then once it had completed set another property on one of the entity's components. I understand that I could use the FromToByAction to control the opacity (and have this working), but I am interested to learn how to create my own dedicated EntityAction, and finding the documentation hard to fathom. I got as far as creating a struct conforming to EntityAction protocol: var animatedValueType: (any AnimatableData.Type)? } Subscribing to update events on this: FadeUpAction.subscribe(to: .updated) { event in guard let animationState = event.animationState else { return } // My animation state is always nil, so I never get here! let newValue = \\\Some Calc... animationState.storeAnimatedValue(newValue) } And setting it up as an animation on an entity: let action = FadeUpAction() if let animation = try? AnimationResource.makeActionAnimation( for:action, duration: 2.0, bindTarget: .opacity ) { entity.playAnimation(animation) } ...but haven't been able to understand how to extract the current timeDelta or set the value in the event handler. Any pointers?
2
0
590
Oct ’24
Subdivision shows in RealityComposerPro but not when loaded in Simulator
Hello, I am trying to use the subdivision mesh rendering option. I can see it working in RealityComposerPro: But not when loading asset and displaying in Simulator: Using this code: import SwiftUI import RealityKit import RealityKitContent struct AirspaceView: View { // MARK: - VIEW BODY var body: some View { RealityView { content in if let a = try? await Entity(named: "Models/Test/Test.usdc", in: realityKitContentBundle) { content.add(a) } } } } Any ideas why?
2
1
552
Feb ’25
When to use an AnchorEntity or HandTrackingProvider in VisionOS
As I understand it there are two ways I can track a hand, or a joint, in RealityKit: either, create an AnchorEntity, for example AnchorEntity(.hand(.left, location: .palm)) or, set up an ARSession with a HandTrackingProvider ( a lot more code which I haven't repeated here). Assuming this is correct, when would I want to use one over the other?
2
0
409
Mar ’25
SwiftUI TextField selection - strange initial values with iOS
When using a TextField with axis to set to .vertical on iOS, it sets a bound selection parameter to an erroneous value. Whilst on MacOS it performs as expected. Take the following code: import SwiftUI @main struct SelectionTestApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @FocusState private var isFocused: Bool @State private var text = "" @State private var textSelection: TextSelection? = nil var body: some View { TextField("Label", text: $text, selection: $textSelection, axis: .vertical) .onChange(of: textSelection, initial: true) { if let textSelection { print("textSelection = \(textSelection)") } else { print("textSelection = nil") } } .focused($isFocused) .task { isFocused = true } } } Running this on MacOS target gives the following on the console: textSelection = nil textSelection = TextSelection(indices: SwiftUI.TextSelection.Indices.selection(Range(0[any]..<0[any])), affinity: SwiftUI.TextSelectionAffinity.downstream) Running the code on iOS gives: textSelection = TextSelection(indices: SwiftUI.TextSelection.Indices.selection(Range(1[any]..<1[any])), affinity: SwiftUI.TextSelectionAffinity.upstream) textSelection = TextSelection(indices: SwiftUI.TextSelection.Indices.selection(Range(1[any]..<1[any])), affinity: SwiftUI.TextSelectionAffinity.upstream) Note here the range is 1..<1 - which is incorrect. Also of side interest this behaviour changes if you remove the axis parameter: textSelection = nil Am I missing something, or is this a bug?
2
0
139
Oct ’25