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 ) ) } }
4w
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.
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.
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 }
Apr ’24