Posts

Post marked as solved
2 Replies
286 Views
In a SwiftUI VisionOS app that opens with one .plain window and another .volumetric window, I want to automatically close the Volume when the user closes the plain window. Attempting to do so with ContentView().onDisappear{ dismissWindow(id: kVolumeId) } results in Page tried to end immersive session initiated by a different page I have not found that error documented anywhere. Any advice?
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
0 Replies
314 Views
Is there any way to specify a clip volume or clipping planes on either a RealityView or the underlying RealityKit entity on visionOS? This was easy on SceneKit with shader modifiers, or in OpenGL, or WebGL, or with RealityKit on iOS or macOS with CustomMaterial surface shader, but CustomMaterial is not supported on visionOS.
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
0 Replies
1k Views
Is it possible to set the isAlternate property on an NSMenuItem in the macOS menubar to implement dynamic menu items in a SwiftUI document-based app which uses CommandMenu to construct the menus?
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
2 Replies
1.4k Views
In trying to implement a custom variation of HSplitView/VSplitView for macOS, I found it impossible to achieve correct behavior of the NSCursor while dragging the split view divider. Something else is resetting NSCursor to an arrow cursor when a SwiftUI view updates. Moving the mouse over the divider View changes the NSCursor to a resize cursor. However, when the insertion is blinking, after 1/2 a second, on the blink the cursor changes back to an arrow. Turning off "blink", then hovering over the divider, the NSCursor stays as a resize cursor. However, as soon as you click and drag to move the divider, again it changes back to an arrow cursor, flashing between the two NSCursor as you move the divider. It seems like something in SwiftUI is doing this, but I can't tell. Is it possible to implement a custom VSplitView within SwiftUI and achieve consistent behavior of the NSCursor? Full code below import AppKit import SwiftUI @main struct NSCursorBugApp: App { var body: some Scene { WindowGroup { ContentView() } } } let blinkTimer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect() struct ContentView: View { @State var position = 20.0 @State var opacity = 1.0 @State var blink = true var body: some View { VStack(alignment: .leading, spacing: 0) { Color.gray .frame(height: position - 4) .overlay{ Rectangle().frame(width: 1, height: 20).opacity(opacity).padding(.trailing, 200).padding(20) } PaneDivider(position: $position) Color.cyan Toggle("Blink", isOn: $blink) } .onReceive(blinkTimer) {_ in if blink { opacity = 1 - opacity } } .frame(width: 500, height: 500) .coordinateSpace(name: "stack") } } struct PaneDivider: View { @Binding var position: Double let dividerSize = 8.0 let circleSize = 6.0 var body: some View { Group { Divider() ZStack { Rectangle().fill(Color(white: 0.99)) Circle().frame(width: circleSize, height: circleSize).foregroundColor(Color(white: 0.89)) }.frame(height: 8) Divider() } #if os(macOS) .background(NSCursorView()) #endif .gesture(DragGesture(minimumDistance: 1, coordinateSpace: .named("stack")) .onChanged { position = max(0, $0.location.y) }) } } /// Helper NSView as .background to SwiftUI PaneDivider View to set resize NSCursor when inside view bounds class NSCursorPlatformView : NSView { var horizontal = true var trackingArea: NSTrackingArea? = nil func clearTrackingAreas() { if let trackingArea = trackingArea { removeTrackingArea(trackingArea) } trackingArea = nil } override func updateTrackingAreas() { clearTrackingAreas() let area = NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .mouseMoved, .activeInKeyWindow], owner: self, userInfo: nil) addTrackingArea(area) trackingArea = area } override func viewWillMove(toWindow newWindow: NSWindow?) { if newWindow == nil { clearTrackingAreas() } else { updateTrackingAreas() } } override func mouseEntered(with event: NSEvent) { updateCursor(with: event) } override func mouseExited(with event: NSEvent) { updateCursor(with: event) } override func mouseMoved(with event: NSEvent) { updateCursor(with: event) } override func cursorUpdate(with event: NSEvent) {} // to stop system from resetting cursor after us func updateCursor(with event: NSEvent) { let p = convert(event.locationInWindow, from: nil) if bounds.contains(p) { (horizontal ? NSCursor.resizeUpDown : NSCursor.resizeLeftRight).set() } else { NSCursor.arrow.set() } } } struct NSCursorView: NSViewRepresentable { var horizontal = true func makeNSView(context: Context) -> NSCursorPlatformView { let view = NSCursorPlatformView() view.horizontal = horizontal return view } func updateNSView(_ nsView: NSCursorPlatformView, context: Context) { } }
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
1 Replies
1.1k Views
Due to limitations of SwiftUI VSplitView, and to preserve the appearance of the old C++/AppKit app I'm porting to SwiftUI, I rolled my own pane divider. It worked well on macOS 11, but after updating to macOS 12, it now triggers an infinite loop somewhere. Running the code below in an Xcode playground works for a short while, but if you wiggle the mouse up and down, after a few seconds it will get caught in an infinite loop: import SwiftUI import PlaygroundSupport import AppKit import CoreGraphics PlaygroundPage.current.setLiveView(ContentView()) struct ContentView: View { @State var position: Double = 50 var body: some View { VStack(spacing: 0) { Color.red .frame(maxHeight: position) PaneDivider(position: $position) Color.blue } .frame(width: 500, height:500) } } struct PaneDivider: View { @Binding var position: Double @GestureState private var isDragging = false // Will reset to false when dragging has ended var body: some View { Group { Divider() ZStack { Rectangle().fill(Color(white: 0.99)) Circle().frame(width: 6, height: 6).foregroundColor(Color(white: 0.89)) }.frame(height: 8) Divider() } .gesture(DragGesture() .onChanged { position += $0.translation.height if position < 0 { position = 0 } } .updating($isDragging) { (value, state, transaction) in state = true }) } } Any thoughts on how to diagnose or fix that?
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
0 Replies
353 Views
Graphing Calculator is a SwiftUI macOS FileDocument-based app. There is a slider that can be set to animate on loop, changing a value continuously animating equations. When it is playing the View menu, and Open Recent, Revert and Share submenus flicker and vanish. The animation is changing a published property of an ObservableObject in the FileDocument. Any advice on how to go about fixing this in the app? Is there a way to be notified within the SwiftUI app lifecycle, when the user clicks in the macOS menu bar in order to pause the animation for the duration of the menu selection?
Posted
by avitzur.
Last updated
.
Post not yet marked as solved
0 Replies
424 Views
I'm trying to animate properties of an @ObservedObject in an NSViewRepresentable using withAnimation but the change happens instantly, and breakpoints in my animatableData get/setters are not touched. Is that a reasonable thing to attempt? When does SwiftUI look for animatableData? Any advice on how to go about it?
Posted
by avitzur.
Last updated
.