Hah! You were right, but you shouldn't have been, BabyJ. I added 4 parentheses and it worked:
struct ContentView: View {
var body: some View {
VStack {
HStack {
Button("Hi") { print("Hi!") }
Button("Hello") { print("Hello!") }
Button("Good evening") { print("Good evening!") }
}
(EqualWidthHStack()) {
Button("Hi") { print("Hi!") }
Button("Hello") { print("Hello!") }
Button("Good evening") { print("Good evening!") }
}
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
}
}
Thanks, Bryan. I'll wait for the next version of Xcode and then file a radar.
@jonasmw:
I am able to reject invalid strings - which can be created by adding an invalid character from the keyboard or pasting in, in my function entryChecker.check(entry)
In my code I have this:
TextField("0.0", text: $entry)
.focused($entryFocused)
.onChange(of: entry, perform: checkEntry)
func checkEntry(value: String) { entryChecker.check(entry: $entry) }
private var entryChecker = FloatEntryValidator(maxlen: 10)
class FloatEntryValidator {
init(maxlen: Int? = nil) { self.maxlen = maxlen}
private let maxlen: Int?
private var prevValidEntry = ""
func check(entry: Binding<String>) {
let value = entry.wrappedValue
if value.isValidFloatEntry(maxlen: maxlen) {
prevValidEntry = value
} else {
entry.wrappedValue = prevValidEntry // Reset
}
}// check
}// FloatEntryValidator
public let minusSign: Character = NumberFormatter().minusSign?.first ?? "-"
public let decimalSep: Character = NSLocale.current.decimalSeparator?.first ?? "."
extension String {
func isValidFloatEntry(maxlen: Int? = nil) -> Bool { // Values that a TextEdit can be allowed to have as the user enters a floating point number
if let maxlen = maxlen, count > maxlen {
return false
}
var parser = StringParser(self)
parser.skipOptional(char: minusSign)
parser.skipDecimals()
parser.skipOptional(char: decimalSep)
parser.skipDecimals()
return parser.finished
}// isValidFloatEntry
}
struct StringParser { // For verifying that a string conforms to specific pattern of sequence. It is valid if finished is true at the end
public init(_ s: String) { string = s; index = s.startIndex }
public let string: String
private var index: String.Index
public var finished: Bool { return index == string.endIndex }
public mutating func skipOptional(char: Character) { // Skip single character that is permitted at the
if !finished && string[index] == char {
index = string.index(after: index)
}
}// skipOptional(Character)
public mutating func skipDecimals() { // Advances index to first place that is not a decimal digit
while !finished {
let uss = string[index].unicodeScalars
if uss.count > 1 || !CharacterSet.decimalDigits.contains(uss.first!) {
return
}
index = string.index(after: index)
}
}// skipDecimal
}// StringParser
Post not yet marked as solved
Thanks. I got it working somehow. Not sure if it was a change in Xcode.
As you requested, here is the code for deleting:
func deleteConversion(at offsets: IndexSet) { conversions.remove(atOffsets: offsets) }
conversions is defined like this:
@AppStorage("savedConversions") var conversions: [IDLine] = []
IDLine is this:
struct IDLine: Identifiable, Codable { // To allow SwiftUI List to correctly edit with some strings repeated
let id: Int
let line: String
}// IDLine
Thanks for your answers, guys. It may be that SwiftUI has been debugged or improved in some way since I ran into this, but in the end, I was able to simply add this line to the TextField:
TextField("0.0", text: $entry)
.onChange(of: entry, perform: checkEntry)
given these declarations:
@AppStorage("entry") private var entry = "0"
(Of course the @AppStorage is not part of this solution)
and
func checkEntry(value: String) { entryChecker.check(entry: $entry) }
No, sorry travis78701. I know about that handler. I need to intercept each character. onChange only deals with changes to the whole work when you leave the TextField.
Post not yet marked as solved
Thanks
.keyboardType(.decimalPad)
is exactly what I wanted.
But there doesn't seem to be a way to intercept keystrokes the way I am using
textField(_:shouldChangeCharactersIn:replacementString:)
I think that provides a better user experience.
Post not yet marked as solved
I don't see iOS 14 in the list of simulators either, looking in Preferences | Components. I guess that means we can't use the SwifUI App life-cycle
Post not yet marked as solved
So far so good. I have installed the latest version of XCode. When I ran it, it gave the normal message about installing something, and I still only have the ones I left from the older OSes.
Post not yet marked as solved
I have been brave and deleted all but the last of the version of iOS 7 - 11, and now I have a decent amount more of GB available.I ran XCode and it said it needed to download something, but it wasn't much in terms of GB.
Thanks!I have settled on this code, and it works, and looks obvious:class XBSelectRecord: UIViewController {
convenience init(heading: String?)
{
self.init(nibName: "XBSelectRecord", bundle: nil)
self.heading = heading
}I find the rules around initializers a bit confusing, so the simplicity is beguiling here.
Post not yet marked as solved
I have the latest macos - 10.15 Beta (19A573a) - and the latest Xcode - 11.0 (11A420a), and playgounds are not working for me at all. I started a new one for ios and then the spinner in the activity viewer (the message area at the top of the window) never stops and the text there just says "Running [file name]" endlessly.Probably a bug in the app somewhere.
"Feedback-Assistent.app" should be "Feedback-Assistant.app"
Post not yet marked as solved
I'm having problems with iCloud in finder. It seemed to be an infinite recursion of subdirectories called icloud. And I couldn't open Numbers. And this is 10.15 19A489l, which was the one that came out yesterday.Forrtunately, I am able to edit my numbers document using icloud.com. It may be slow, but it is a lifesaver.