Post

Replies

Boosts

Views

Activity

Reply to TextField .alignmentGuide in Form leading point varies?
Originally I just passed a label to the actual TextField but could not get the desired effect. This is the solution I'm using but I find it unsatisfactory. I wrap each form item in LabeledContent. It does not look as tidy as the Form label formatting but without it when I use .alignmentGuide it operates from a unique origin which depends on the label but simply adjusting for the label length does not give consistent results. Form { LabeledContent { CustomField( thing: $activeThing, setValue: { thingtype, newValue in thingtype.thing = newValue } ) } label: { Text(shortLabel) .frame(width: longLabelWidth, alignment: .trailing) } CustomField( thing: $activeThing, setValue: { thingtype, newValue in thingtype.thing = newValue } ) } label: { Text(longLabel) .frame(width: longLabelWidth, alignment: .trailing) } } struct CustomField: View { ... var body: some View { TextField("", text: $displayText) .inlineCompletion( text: displayText, completion: completion, ) .onAppear {displayText = getValue(transaction)} struct InlineCompletion: ViewModifier { let text: String let completion: String func body(content: Content) -> some View { ZStack(alignment: .leading) { content if !completion.isEmpty { Text(completion) .foregroundColor(.secondary) .opacity(text.isEmpty ? 0 : 0.7) .alignmentGuide(.leading) { _ in -textWidth(text) - baseFontSize } } } } } extension View { func inlineCompletion(text: String, completion: String) -> some View { modifier( InlineCompletion( text: text, completion: completion ) ) } }
Topic: UI Frameworks SubTopic: SwiftUI
Feb ’25
Reply to NSExpression error handling
Thanks for making that clear. For the sake of helping anyone else with this issue, my solution is to use a pair of functions which cleans the typed expression as best it can but then calmly handles errors on any remaining malformed input private func handleSubmit() { print("handling submit") if let result = safelyEvaluateExpression() { inputExpression = result isError = false } else { isError = true } } private func safelyEvaluateExpression() -> String? { let preparedExpression = inputExpression .replacingOccurrences(of: "×", with: "*") .replacingOccurrences(of: "÷", with: "/") .trimmingCharacters(in: .whitespacesAndNewlines) guard !preparedExpression.isEmpty else { return nil } let allowedChars = CharacterSet(charactersIn: "0123456789.+-*/() ") guard preparedExpression.unicodeScalars.allSatisfy({ allowedChars.contains($0) }) else { return nil } if let result = NSExpressionWrapper.evaluateExpression(preparedExpression) { return String(format: "%.2f", result.doubleValue) } return nil } with: // NSExpressionWrapper.h #import <Foundation/Foundation.h> @interface NSExpressionWrapper : NSObject + (NSNumber *)evaluateExpression:(NSString *)string; @end and // NSExpressionWrapper.m #import "NSExpressionWrapper.h" @implementation NSExpressionWrapper + (NSNumber *)evaluateExpression:(NSString *)string { @try { NSExpression *expression = [NSExpression expressionWithFormat:string]; return [expression expressionValueWithObject:nil context:nil]; } @catch (NSException *exception) { // Log if needed NSLog(@"Caught exception: %@", exception.reason); return nil; // Return nil on error } } @end In the SwiftUI code I use isError to overlay the TextField to let the user know they have work to do. Claude helped me with this code. I am not a programmer. I'm disappointed that I need to use Obj-C code and not stick to Swift in order to allow simple inline math but perhaps with the advent of math in apps like Notes there will be a Swift solution in the future.
Topic: Programming Languages SubTopic: Swift Tags:
Jan ’25
Reply to Recursion in a SwiftUI Table
I've not gotten anywhere with this. The issue is how does one abstract code from within a DisclosureTableRow and return either another DisclosureTableRow or a TableRow. Why not organize the accounts hierarchically and feed that to Table? Because then childless parents have disclosure triangles and there are issues with expansion.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’24
Reply to .dropDestination on TableRow updated recently?
My solution, which I learned from elsewhere on this forum, is just to drag the unique name property of my object as a String and then in the action closure use the name to find the dropped object. Interestingly, when I try to abstract this modifier the compiler expects the elements that prevent compilation; perhaps this would work with something more specific than some View. struct DropableTableRowModifier: ViewModifier { let object: Object: func body(content: Content) -> some View { content .dropDestination(for: String.self) { objectNames in // do things with object and objectNames return }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’24
Reply to SwiftUI Search Bar and Scope Filters
on MacOS the search bar is trailing but the scope buttons are leading when they appear below the bar. Any way to get them aligned with the start of the search bar or at least trailing?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jul ’25
Reply to SwiftUI subview .frame ignored on parent view appear, MacOS
Adding .layoutPriority(1) to Text("left view") seems to have solved the problem. Still not sure if this is the best way to go so open to other ideas,
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Mar ’25
Reply to TextField .alignmentGuide in Form leading point varies?
Originally I just passed a label to the actual TextField but could not get the desired effect. This is the solution I'm using but I find it unsatisfactory. I wrap each form item in LabeledContent. It does not look as tidy as the Form label formatting but without it when I use .alignmentGuide it operates from a unique origin which depends on the label but simply adjusting for the label length does not give consistent results. Form { LabeledContent { CustomField( thing: $activeThing, setValue: { thingtype, newValue in thingtype.thing = newValue } ) } label: { Text(shortLabel) .frame(width: longLabelWidth, alignment: .trailing) } CustomField( thing: $activeThing, setValue: { thingtype, newValue in thingtype.thing = newValue } ) } label: { Text(longLabel) .frame(width: longLabelWidth, alignment: .trailing) } } struct CustomField: View { ... var body: some View { TextField("", text: $displayText) .inlineCompletion( text: displayText, completion: completion, ) .onAppear {displayText = getValue(transaction)} struct InlineCompletion: ViewModifier { let text: String let completion: String func body(content: Content) -> some View { ZStack(alignment: .leading) { content if !completion.isEmpty { Text(completion) .foregroundColor(.secondary) .opacity(text.isEmpty ? 0 : 0.7) .alignmentGuide(.leading) { _ in -textWidth(text) - baseFontSize } } } } } extension View { func inlineCompletion(text: String, completion: String) -> some View { modifier( InlineCompletion( text: text, completion: completion ) ) } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
Boosts
Views
Activity
Feb ’25
Reply to NSExpression error handling
Thanks for making that clear. For the sake of helping anyone else with this issue, my solution is to use a pair of functions which cleans the typed expression as best it can but then calmly handles errors on any remaining malformed input private func handleSubmit() { print("handling submit") if let result = safelyEvaluateExpression() { inputExpression = result isError = false } else { isError = true } } private func safelyEvaluateExpression() -> String? { let preparedExpression = inputExpression .replacingOccurrences(of: "×", with: "*") .replacingOccurrences(of: "÷", with: "/") .trimmingCharacters(in: .whitespacesAndNewlines) guard !preparedExpression.isEmpty else { return nil } let allowedChars = CharacterSet(charactersIn: "0123456789.+-*/() ") guard preparedExpression.unicodeScalars.allSatisfy({ allowedChars.contains($0) }) else { return nil } if let result = NSExpressionWrapper.evaluateExpression(preparedExpression) { return String(format: "%.2f", result.doubleValue) } return nil } with: // NSExpressionWrapper.h #import <Foundation/Foundation.h> @interface NSExpressionWrapper : NSObject + (NSNumber *)evaluateExpression:(NSString *)string; @end and // NSExpressionWrapper.m #import "NSExpressionWrapper.h" @implementation NSExpressionWrapper + (NSNumber *)evaluateExpression:(NSString *)string { @try { NSExpression *expression = [NSExpression expressionWithFormat:string]; return [expression expressionValueWithObject:nil context:nil]; } @catch (NSException *exception) { // Log if needed NSLog(@"Caught exception: %@", exception.reason); return nil; // Return nil on error } } @end In the SwiftUI code I use isError to overlay the TextField to let the user know they have work to do. Claude helped me with this code. I am not a programmer. I'm disappointed that I need to use Obj-C code and not stick to Swift in order to allow simple inline math but perhaps with the advent of math in apps like Notes there will be a Swift solution in the future.
Topic: Programming Languages SubTopic: Swift Tags:
Replies
Boosts
Views
Activity
Jan ’25
Reply to MacOS SwiftUI access modelContext from menu (.commands)?
I added a .sheet in Main where I can access the shared modelContext and all is well. I'd still appreciate answers to #3
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’24
Reply to Recursion in a SwiftUI Table
I've not gotten anywhere with this. The issue is how does one abstract code from within a DisclosureTableRow and return either another DisclosureTableRow or a TableRow. Why not organize the accounts hierarchically and feed that to Table? Because then childless parents have disclosure triangles and there are issues with expansion.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’24
Reply to .dropDestination on TableRow updated recently?
My solution, which I learned from elsewhere on this forum, is just to drag the unique name property of my object as a String and then in the action closure use the name to find the dropped object. Interestingly, when I try to abstract this modifier the compiler expects the elements that prevent compilation; perhaps this would work with something more specific than some View. struct DropableTableRowModifier: ViewModifier { let object: Object: func body(content: Content) -> some View { content .dropDestination(for: String.self) { objectNames in // do things with object and objectNames return }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’24
Reply to @Environment for new @Observable macro not creating bindings?
I had read that the answer was to mark the shared object with @Binding instead of @State but that was not sufficient. See https://developer.apple.com/forums/thread/735416?answerId=761483022#761483022 In my case I needed to add the equivalent of @Bindable var profile = profile // must be placed in view body
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Dec ’23