Posts

Post not yet marked as solved
0 Replies
124 Views
I have a view, and in this view I bind Axis class values — lowerBound which is a regular property and at – computed one which comes from protocol HasPositionProtocol associated with Axis. struct AxisPropertiesView<Axis>: View where Axis: StyledAxisProtocol, Axis: HasPositionProtocol, Axis: Observable { @Bindable var axis: Axis var body: some View { HStack { TextField("", text: $axis.shortName) .frame(width: 40) TextField("", value: $axis.lowerBound, format: .number) .frame(width: 45) //Problem is here: Slider(value: $axis.at, in: axis.bounds) ... Unfortunately I got en error Failed to produce diagnostic for expression; ... for whole View. But if I remove Slider from View, error disappeared. What could cause this strange behaviour? Value of .at comes from: public extension HasPositionProtocol { ///Absolut position on Axis var at: Double { get { switch position { case .max: return bounds.upperBound case .min: return bounds.lowerBound case .number(let number): return number } } set { switch newValue { case bounds.lowerBound: position = .min case bounds.upperBound: position = .max default: position = .number(newValue) } } } }
Posted
by ludzik.
Last updated
.
Post marked as solved
2 Replies
3.1k Views
I have a ZStack view embedded in ScrollView. The height of ZStack often changes. var body: some View { ScrollView([.vertical, .horizontal], showsIndicators: true) {             VStack { // embedding in VStack doesn't change behaviour                 ZStack () {                     ForEach(mapElements.indices, id:\.self) { i in                         let element = mapElements[i]                         MapElementView (mapElement: element)                         .position(x: offset(x: element.x),                                   y: offset(y: element.y))                         .zIndex(5)                         MakeConnections(mapElement: element)                     }                 }.frame(width: calculateWidth(),                         height: calculateHeight())                 }                 Rectangle() // Just to make VStack filled             }         }.frame(alignment: .topLeading) } Some scroll views (ie. list) always align embedded objects to top even they are shorter than embedding scroll view. But in this case ZStack is always centred when view is refreshed. Is it possible to define behaviour, so each change of a content will align its top to scroll view top, even if height of ZStack is smaller than ScrollView?
Posted
by ludzik.
Last updated
.
Post marked as solved
1 Replies
848 Views
I have a MacOS package dependency which defines some class: FontPens import Foundation ... public class BoundsPen: Pen { var bounds = CGRect.null private var currentPoint = CGPoint.zero .... After upgrading Xcode to 14.1 both lines throws errors Type 'CGRect' has no member 'null' and Type 'CGPoint' has no member 'zero'. Calling CGPoint.zero and CGRect.null from an app is OK if Foundation is imported. Is it a way to solve this problem without changing package source?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
0 Replies
477 Views
I have a MacOS app which has a lot of TextFields in many views; and one editor view which has to receive pressed keyboard shortcut, when cursor is above. But as I try, I cannot focus on a view which is not text enabled. I made a small app to show a problem: @main struct TestFocusApp: App { var body: some Scene { DocumentGroup(newDocument: TestFocusDocument()) { file in ContentView(document: file.$document) } .commands { CommandGroup(replacing: CommandGroupPlacement.textEditing) { Button("Delete") { deleteSelectedObject.send() } .keyboardShortcut(.delete, modifiers: []) } } } } let deleteSelectedObject = PassthroughSubject<Void, Never>() struct MysticView: View { var body: some View { ZStack { Rectangle() .foregroundColor(.gray.opacity(0.3)) }.focusable() .onReceive(deleteSelectedObject) { _ in print ("received") } } } enum FocusableField { case wordTwo case view case editor case wordOne } struct ContentView: View { @Binding var document: TestFocusDocument @State var wordOne: String = "" @State var wordTwo: String = "" @FocusState var focus: FocusableField? var body: some View { VStack { TextField("one", text: $wordOne) .focused($focus, equals: .wordOne) TextEditor(text: $document.text) .focused($focus, equals: .editor) ///I want to receive DELETE in any way, in a MystickView or unfocus All another text views in App to not delete their contents MysticView() .focusable(true) .focused($focus, equals: .view) .onHover { inside in focus = inside ? .view : nil /// focus became ALWAYS nil, even set to `.view` here } .onTapGesture { focus = .view } TextField("two", text: $wordTwo) .focused($focus, equals: .wordTwo) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView(document: .constant(TestFocusDocument())) } } Only first TextField became focused when I click or hover over MysticView I can assign nil to focus, but it will not unfocus fields from outside this one view. Is it a bug, or I missed something? How to make View focusable? To Unfocus all textFields?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
1 Replies
1.7k Views
I build a graphic editor. Dragging points through my canvas is smooth and fast. But when I try to display data in outline view everything slows down to 2 FPS. First I suspected slow data access, but when I check app in Instruments I found Core Animation Commits are displayed as a red blocks and Time Profiler bit busy. Is a way to disable Core Animation for some views? Or this message is misleading?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
0 Replies
459 Views
I have a VSplitView with two views inside. But each time app starts proportions are set to 50/50, each one has the same height. I would like to set height of one of them to some number, (and save it in defaults... not most important thing). Of course I would like to change this height manually if I need to.     var body: some View {         return VSplitView { HigherView(with: someContent) // Let it be float height ShorterView(with: anotheContent) // let it height will be 300 when fired first time } } Is it very hard?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
1 Replies
817 Views
As in a title: even empty new app has menu with working menu items, but with disabled and not working keyboard shortcuts. Is it bug, feature or I should do something to enable them? Minimize, Zoom... works. My Edit Menu have the same problem: Commands Undo, Redo and Delete works when chosen from menu, but calling them via keyboard causes only cursor disappear.
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
1 Replies
1k Views
I'm trying to learn how UndoManager works. I made a small app to Undo/Redo something. And I have few questions, I cannot find answer in documentation: I know UndoManager could be accessed in View via @Environment(\.undoManager) var undoManager Brilliant. But in this case it's only available in a View, if I want use it somewhere deeper in a structure I have to pass it via Model to Objects... Is a way to access the same UndoManager in other objects? Models, Data... I could be much more convenient, specially if there is many Undo groupings. If I create UndoManager in Document (or somewhere else) it's not visible for main menu Edit -> Undo, Redo In the app repository on GitHub I implemented Undo/Redo. For me (haha) it looks OK and even works, but not for first action. First action Undo causes Thread 1: signal SIGABRT error. After three actions I can undo two last actions... Bang. Something is wrong import Foundation import SwiftUI struct CustomView: View { @ObservedObject var model: PointsViewModel @Environment(\.undoManager) var undoManager @GestureState var isDragging: Bool = false @State var dragOffsetDelta = CGPoint.zero var formatter: NumberFormatter { let formatter = NumberFormatter() formatter.allowsFloats = true formatter.minimumFractionDigits = 2 formatter.maximumFractionDigits = 5 return formatter } var body: some View { HStack { VStack(alignment: .leading, spacing: 10) { ForEach(model.insideDoc.points.indices, id:\.self) { index in HStack { TextField("X", value: $model.insideDoc.points[index].x, formatter: formatter) .frame(width: 80, alignment: .topLeading) TextField("Y", value: $model.insideDoc.points[index].y, formatter: formatter) .frame(width: 80, alignment: .topLeading) Spacer() } } Spacer() } ZStack { ForEach(model.insideDoc.points.indices, id:\.self) { index in Circle() .foregroundColor(index == model.selectionIndex ? .red : .blue) .frame(width: 20, height: 20, alignment: .center) .position(model.insideDoc.points[index]) //MARK: - drag point .gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local) .onChanged { drag in if !isDragging { dragOffsetDelta = drag.location - model.insideDoc.points[index] model.selectionIndex = index let now = model.insideDoc.points[index] undoManager?.registerUndo(withTarget: model, handler: { model in model.insideDoc.points[index] = now model.objectWillChange.send() }) undoManager?.setActionName("undo Drag") } model.insideDoc.points[index] = drag.location - dragOffsetDelta } .updating($isDragging, body: { drag, state, trans in state = true model.objectWillChange.send() }) .onEnded({drag in model.selectionIndex = index model.insideDoc.points[index] = drag.location - dragOffsetDelta model.objectWillChange.send() }) ) } }.background(Color.orange.opacity(0.5)) //MARK: - new point .gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local) .onEnded{ loc in let previousIndex = model.selectionIndex undoManager?.registerUndo(withTarget: model, handler: {model in model.insideDoc.points.removeLast() model.selectionIndex = previousIndex model.objectWillChange.send() }) model.insideDoc.points.append(loc.location) model.selectionIndex = model.insideDoc.points.count - 1 model.objectWillChange.send() } ) //MARK: - delete point .onReceive(deleteSelectedObject, perform: { _ in if let deleteIndex = model.selectionIndex { let deleted = model.insideDoc.points[deleteIndex] undoManager?.registerUndo(withTarget: model, handler: {model in model.insideDoc.points.insert(deleted, at: deleteIndex) model.objectWillChange.send() }) undoManager?.setActionName("remove Point") model.insideDoc.points.remove(at: deleteIndex) model.objectWillChange.send() model.selectionIndex = nil } }) } } } Any comments about quality of my algorithms will be highly appreciated.
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
3 Replies
3.9k Views
Maybe I missed something — is it possible to somehow edit / change / customise main menu in SwiftUI App lifecycle? I made a document based App, I can read, write, even Recent Documents have for free. But how to add or remove Items, and connect them with app in pure SwiftUI way? With no AppKit, pure?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
0 Replies
462 Views
I try to build an app in MacOS SwiftUI, where two different subviews of main contentView shows different parts of Axis element:struct ContentView: View { &#9;&#9;@Binding var document: GlyphDesignerDocument &#9;&#9; &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;//Axes Sliders Slider causes explosion AxesSlidersView(axes: $document.axes) AxesView(axes: $document.axes, addRows: {document.axes.insert(Axis("z", bounds: 0...1000), at: $0)}, removeRows: {document.axes.remove(at: $0)}, addAxis: {document.axes.append(Axis("z", bounds: 0...1000))}) } } Subviews works great, everything updates in both ways, but application hangs-up when AxisView will delete one Axis from axes array. All experimental code (still changing) is available at https://github.com/typoland/GlyphDesignerTest AxesView looks like this: &#9;&#9;struct AxesView : View { &#9;&#9;&#9;&#9;@Binding var axes: [Axis] &#9;&#9;&#9;&#9;@State var selected: Int? = nil &#9;&#9;&#9;&#9;var addRows: (_ at:Int) -> Void &#9;&#9;&#9;&#9;var removeRows: (_ at: Int) -> Void &#9;&#9;&#9;&#9;var addAxis: () -> Void &#9;&#9;&#9;&#9;var body: some View { &#9;&#9;&#9;&#9;&#9;&#9;VStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.... Shows Axes &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;struct AxisView: View { &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;@Binding var axis: Axis &#9;&#9;&#9;&#9;var insert: () -> Void &#9;&#9;&#9;&#9;var delete: () -> Void &#9;&#9;&#9;&#9;@Binding var selected: Bool &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;var body: some View { &#9;&#9;&#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9; //Makes ForEach for each Axis, adds buttons to insert and delete, more parameters of an Axis... &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;struct AxesSlidersView: View { &#9;&#9;&#9;&#9;@Binding var axes: [Axis] &#9;&#9;&#9;&#9;var body: some View { &#9;&#9;&#9;&#9;&#9;&#9;VStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ForEach(axes.indices, id:\.self) {index in &#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; Text("\(axis.name)") &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Slider (value: $axes[index].at, in: axis.bounds) &#9;&#9; } } &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9; After suggestion received on stackoverflow I changed: Slider (value: $axes[index].at, in: axis.bounds) to Slider (value: Bound(get: {axis.ataxes[index].at}, set: {axes[index].at = $0}, in: axis.bounds) This way I can delete axis without explosion, but, second view does not live update anymore. Is it SwiftUI problem? How to deal with this? @Binding arrays is somehow broken?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
1 Replies
1.7k Views
I have a struct:public typealias CoordUnit = Double public struct StyledAxis: StyledAxisProtocol { &#9;&#9;public var name: String &#9;&#9;public var bounds: ClosedRange<CoordUnit> &#9;&#9;public var distribution: Double? ... } In SpaceAxisProtocol bounds are defined as: &#9;&#9;public protocol SpaceAxisProtocol: Equatable & Hashable { &#9;&#9;&#9;&#9;var name: String {get set} &#9;&#9;&#9;&#9;var bounds: ClosedRange<CoordUnit> {get set} &#9;&#9;&#9; init(_ name: String, bounds: ClosedRange<CoordUnit>) &#9;&#9;} &#9;&#9;public protocol StyledAxisProtocol: SpaceAxisProtocol {...} And I try to edit bounds in a View: &#9;&#9;struct StyledAxisView<SA:StyledAxisProtocol>: View { &#9;&#9;&#9;&#9;@Binding var axis: SA &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;public var body : some View { &#9;&#9;&#9;&#9;&#9;&#9;VStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;// Axis name and distribution works &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;HStack(alignment: .lastTextBaseline) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;TextField("", text: $axis.name) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.controlSize(.small) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.font(.headline) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;DistributionView( &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;value: $axis.distribution) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.controlSize(.mini) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;// It causes compiler `Cannot assign to property: 'lowerBound' is a 'let' constant`. But it isn't. ? &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ValueView(value: $axis.bounds.lowerBound) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;ValueView(value: $axis.bounds.upperBound) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;... When axis.bounds.lowerbound and axis.bounds.upperbound became let? How to edit them in View?
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
1 Replies
593 Views
Good (morning, evening...). I try to build SwiftUI view hierarchy for model where: I have many Glyph objects: var manager: CoordinatesManager var elements: [ ManyMultidimensionalElements ] var path: Path { return Path(..based on elements and manager.currentCoordinates) } I have one CoordinatesManger: var currentCoordinates: [ Coordinate ] In one view I can set currrentCoordinates of CoordinatesManager, in second view I want to see Glyph with actual glyph.manager.currentCoordinates It almost works but:changing manager.currentCoordinates doesn't change GlyphView, even if Glyph object see manager.currentCoordinates was changed (in manger.didSet{...}) When scrolling (why?) glyph.path is recalculated, but View stays untouched. Example Playground - https://developer.apple.com/forums/content/attachment/507e87de-2094-4998-8361-b3c1dd21549c How to push View to redraw? Something like NSView.needsDisplay. How to trigger View to redraw, when glyph.manager.currentCoordinates are changed? PS. It's my first post on this forum, I don't know what's the best: hide Playground file as attachment or list it in main text.
Posted
by ludzik.
Last updated
.
Post not yet marked as solved
0 Replies
485 Views
I made scene: part is defined in a .scn file, bunch of boxes are added progamatically. But after export to .dae, generated boxes are broken: each side has only one triangle, half of side is empty. Also it's impossible to import this file to Blender. Blender quits. Any ideas?
Posted
by ludzik.
Last updated
.