Post

Replies

Boosts

Views

Activity

Reply to Checking the contents of a TextField variable method not working
// Coordinate.swift class Coordinate { var latitude: String var longitude: String init(latitude: String, longitude: String) { self.latitude = latitude self.longitude = longitude } static let defaultCoord: String = "000.000000" static let zeroCoord: Coordinate = .init(latitude: defaultCoord, longitude: defaultCoord) // Moved these into this class as they only need to be created once, and can be accessed via the class itself, i.e. Coordinate.validChars static let validChars: Set<Character> = ["-", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] static let formatIncorrect: String = "May start with a minus and at least 1 number, then a full-stop followed by up to 6 numbers" // This function validates a coordinate by removing unwanted characters, and making sure there's only one minus sign static public func validate(_ coord: String) -> String { var coord_ = coord // Remove invalid characters coord_.removeAll(where: { !validChars.contains($0) } ) // If there's more than one minus sign, remove them all and put one at the beginning // This handles a value like "-12.34-56", transforming it to "-12.3456" if(coord_.filter( { $0 == "-" } ).count > 1) { coord_.removeAll(where: { "-".contains($0) } ) coord_ = "-" + coord_ } // If there's a minus sign, and the first occurrence of it isn't at the beginning // This handles a value like "12.34-56", transforming it to "-12.3456" if(coord_.filter( { $0 == "-" } ).count > 0 && coord_.firstIndex(of: "-")! > coord_.startIndex) { // Remove all the minus signs, and add one to the beginning coord_.removeAll(where: { "-".contains($0) } ) coord_ = "-" + coord_ } return coord_ } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
// Card.swift import Foundation /* This is your Card class. It contains an instance of a Coordinate class that contains the latitude and longitude for a card. It also contains a few example variables to show you how a class can be used. */ class Card: ObservableObject { @Published var coord: Coordinate @Published var name: String @Published var city: String init(coord: Coordinate, name: String, city: String) { self.coord = coord self.name = name self.city = city } /* This allows you to create an empty card, i.e. one with default values. You can do this in any of the following ways: `var newCard: Card = Card.emptyCard` `var newCard: Card = .emptyCard` `var newCard = Card.emptyCard` */ static let emptyCard = Card(coord: Coordinate.zeroCoord, name: "", city: "") }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
// MainApp.swift import SwiftUI @main struct MainApp: App { init() { // The init() function runs when the app starts, so these two functions are executed before the UI is created buildScan() createData() } var body: some Scene { WindowGroup { ContentView() } } } // MARK: - Global vars var gameArray: [String] = [] var cards: [Card] = [] // An array of your Card class // MARK: - Startup functions func buildScan() { let emptyData = "1,,00.000000,00.000000,,,,,,,,2,,00.000000,00.000000,,,,,,,,3,,00.000000,00.000000,,,,,,,,4,,00.000000,00.000000,,,,,,,,5,,00.000000,00.000000,,,,,,,,6,,00.000000,00.000000,,,,,," gameArray = emptyData.components(separatedBy: ",") } func createData() { // Two instances of the Card class are created here and added to the `cards` array. Note the name and city values; they're just example data. cards.append(Card.init(coord: Coordinate(latitude: gameArray[2], longitude: gameArray[3]), name: "Card1", city: "London")) cards.append(Card.init(coord: Coordinate(latitude: gameArray[2], longitude: gameArray[3]), name: "Card2", city: "San Francisco")) }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
Okay, here we go. This answer will be done in a few posts: I've created a Card class, which is where you store the latitude and longitude of the card, and I've added in a couple of other properties so you can see how classes are used. Card is an ObservableObject with @Published variables. It also contains a static let, which is simply a way of letting you access something in a class without having to create an instance of that class. In this example I've added a static let emptyCard which is an instance of Card with default values. You access it with Card.emptycard. You see how you don't access it via an instance of the class? You don't call for emptyCard on a card you've already created. So, you don't do: var myCard: Card = <create the card> followed by myCard.emptyCard. In fact, you cannot do that; it's not possible to access it that way. I've also created a Coordinate class which contains the latitude and longitude for a coordinate. I separated this out because it's a learning exercise for you, but it also makes sense because a coordinate is its own special thing with its own special properties and functions. So... in the Coordinate class there's a static let defaultCoord which can be accessed with Coordinate.defaultCoord. There's a static let zeroCoord which is an instance of Coordinate with the default values. It's used in Card.emptyCard. I've moved the allowed characters Set<Character> here because it made sense. It's used by Coordinates so it makes sense that Coordinate contains that value. The same applies for your error message: static let formatIncorrect: String = "May start with a minus and at least 1 number, then a full-stop followed by up to 6 numbers". Then there's a static public func validate(_ coord: String) -> String { which validates a coordinate by removing unwanted characters, and making sure there's only one minus sign. In the main app - the bit where your app launches from (marked by @main), I've added an init() function that runs your buildScan() function, and also added a function createData() that creates two Cards to use in the code. Finally the ContentView, now that the cards are available, it can properly access them and use them in the UI. I moved the duplicated UI code into its own View struct, and you simply supply whether you're doing the latitude or longitude. The code in the View draws appropriately.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
Okay, it looks like you should probably just use a Regex for this. Here's a completely working example of a latitude and longitude that are being validated by a regex. I'll give you a little commentary after the code: import SwiftUI // Latitude: ^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$ // Longitude: ^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$ let validCoordCharacters: Set<Character> = ["-", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] struct ContentView: View { @State private var cards: card = .init(firstCardLatitude: "-12.345678", firstCardLongitude: "3.987654") @State private var latitudeResult: String = "No result" @State private var longitudeResult: String = "No result" var body: some View { VStack { Text("Latitude") TextField("Enter latitude", text: $cards.firstCardLatitude) .multilineTextAlignment(.center) .onAppear(perform: { if cards.firstCardLatitude.wholeMatch(of: /^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$/) != nil { latitudeResult = "Match" } else { latitudeResult = "No match" // You can uncomment this line to reset the value, if you want //cards.firstCardLatitude = "000.000000" } cards.firstCardLatitude.removeAll(where: { !validCoordCharacters.contains($0) } ) }) .onChange(of: cards.firstCardLatitude) { cards.firstCardLatitude.removeAll(where: { !validCoordCharacters.contains($0) } ) } Text("Result: \(latitudeResult)") Divider() Text("Longitude") TextField("Enter longitude", text: $cards.firstCardLongitude) .multilineTextAlignment(.center) .onAppear(perform: { if cards.firstCardLongitude.wholeMatch(of: /^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$/) != nil { longitudeResult = "Match" } else { longitudeResult = "No match" // You can uncomment this line to reset the value, if you want //cards.firstCardLongitude = "000.000000" } cards.firstCardLongitude.removeAll(where: { !validCoordCharacters.contains($0) } ) }) .onChange(of: cards.firstCardLongitude) { cards.firstCardLongitude.removeAll(where: { !validCoordCharacters.contains($0) } ) } Text("Result: \(longitudeResult)") } .padding() } } struct card { var firstCardLatitude: String var firstCardLongitude: String } #Preview { ContentView() } Lines 3 and 4 are the regex for latitude and longitude, These are just comments. The actual regex is used on lines 20 and 42. Line 6 is that Set<Character> that I explained previously. It is used on lines 32 and 54 to remove any invalid characters from the Strings when they are typed into the TextField. Line 8 creates an instance of my simple cards struct with two vars in. Yours is likely more complex. Lines 10 and 11 create State vars to hold a result. These are just for displaying on the screen in the preview so you can see the results of the validation against the regex. Lines 19 and 41 run the regex when the TextFields appear. They check if the value in the card (line 9) matches the regex. If it does the result is set to "Match". If not, it's set to "No match". The preview is then updated to show you the result. If you change the value in the preview (the iPhone display, not the code!) you'll find that you cannot enter any character other than those in the Set<> because lines 31 and 53 stop you doing that. If, however, you change the values in line 9, you can see what happens. So, for example, if you changed the latitude to "-12.345xyz678" you won't see the "xyz" in the preview (lines 31 and 53 handle that), and you'll see the "No match" text. If you uncomment lines 26 and 48 this will reset the values to "000.000000", which is what you want. I strongly encourage you to read through this code and understand what it's doing. It's not difficult or magic; it's really very simple.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
Moving this back into replies rather than comments, as you can more easily see replies. Let us know exactly what you want your code to do. What are you trying to achieve? You have a latitude text field, and in your original code you wanted to reset the value to "000.000000" if cards.firstCardLatitude had a character that isn't in your array? Then what happens? The user can edit that field and enter anything they like because you didn't have any further code that would handle it. My code handles it. As a user, when I'm typing in a field, if I were to accidentally hit the 't' character when I meant to press '5' ('t' is next to '5' on the keyboard) your code would reset the field; my code simply stops it being added to the string. So, what do you want to achieve? Give us a few steps so we can help you a little more.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
/ is a forward slash. Where does the error happen? Which line? What is cards? Also, char is a Character, and you're trying to compare one Character against an array of Character. Do you mean to use something like if (!allowed.contains(char)) {? From what I can gather you're trying to make sure the value in the field is a valid latitude? There are better functions to do this. You should create a Set of Character. From the documentation: You use a set instead of an array when you need to test efficiently for membership and you aren’t concerned with the order of the elements in the collection, or when you need to ensure that each element appears only once in a collection. So, add this somewhere once only; you don't need to re-create this Set everywhere: let validCoordCharacters: Set<Character> = ["-", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] You're currently stripping out unwanted characters when the TextField first appears, but since it's an editable TextField you should be doing this when the value changes, too: .onChange(of: theTextFieldText) { theTextFieldText.removeAll(where: { !validCoordCharacters.contains($0) } ) } And you will need to ensure that the minus character - is only ever at the beginning of the String for it to be a valid latitude/longitude. You could do this by checking if the String contains that character, and if its location in the String is not location 0, then you remove it from the String and add it to the beginning.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to URLSession.dataTask(with: URL) error: Type of expression is ambiguous without a type annotation
I don't know what you're doing that's causing the issue. Maybe because your `do {} catch {}§ is outside the task? This is a function I use to get some JSON notes from my server: func loadJsonNotesFromServer() { let url = URL(string: kFileLocationServer + kFileNameNotes + ".json")! let config = URLSessionConfiguration.default config.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData let session = URLSession.init(configuration: config) session.dataTask(with: url) {(data, response, error) in do { if let d = data { let data = try JSONDecoder().decode(Notes.self, from: d) DispatchQueue.main.async { self.notes = data.notes } } else { print("Error: No JSON notes data at url: \(url)") self.loadJsonDataFromBundle_Notes() } } catch { print ("Error loading JSON notes data from url: \(url)\nError: \(error)") self.loadJsonDataFromBundle_Notes() } }.resume() } The only difference I can see is your do block is outside the task...?
May ’25
Reply to URLSession.dataTask(with: URL) error: Type of expression is ambiguous without a type annotation
No need to reply if you're within an hour of your original post - you have a one-hour window to edit it :) Anyway, I think this is because you're assigning the task to a let but you haven't provided a type, and because the completion handler returns three different things, the type it returns will be ambiguous. If you don't need to do anything with task later on (which it doesn't look like you do in your code), you can ignore the let, i.e. just use: URLSession.shared.dataTask(with: url) {(data, response, error) in ... }.resume()
May ’25
Reply to Copy Whats new Text from a previous release
Huh? Aside from it being a field called "What's New in This Version", and putting old text in doesn't make much sense, why don't you just go into App Store Connect for the previous release, and copy the text from there? Alternatively, keep a copy of the text you use for each release, and store it in an archive along with the source code and assets etc. for that release. That way, you can always go back to any version of your app and see exactly what you wrote and what code and assets you had. I do this, and base my next version off the previous version by simply copying the archive and increasing the version numbers. If you think Apple should implement this in App Store Connect, you can raise a suggestion at: https://feedbackassistant.apple.com/
Apr ’25