Post

Replies

Boosts

Views

Activity

Reply to Need help
Please don't post photos of your errors. Just copy the error text and paste it here. Have you read the instructions for that API? What does your code look like? You've given us nothing with which we can help you. (You did this in a previous question, too.) If you can't provide us the information required to help you, no one will respond to your posts.
Topic: Community SubTopic: Apple Developers Tags:
May ’25
Reply to I've been fooling around with this and I lose "stuff"
Xcode uses a project file, and the filename is your project name with a .xcodeproj extension, e.g. MyApp.xcodeproj. That project file contains a link to the files you've added to or created within the project in Xcode. Are the files still listed in the project viewer (the left-hand section of Xcode)? If any of the files listed there are in red it means the files are in the project but Xcode can't find them. You might've moved them. Given that you say the projname is duplicated, it's possible you've moved the files inside the projname folder into a new folder called projname inside that folder. If the files are red, you can either drag the files from Finder back into Xcode and remove the red ones, or - and do this one at a time to see if it works - move one file from projname/projname/ into projname/. If it works, you can probably just move them all in one go.
May ’25
Reply to Checking the contents of a TextField variable method not working
It's a little more complicated to explain, but basing everything off the code I've already provided... you have your cards array in the main app: func createData() { // Two instances of the Card class are created here and added to the `cards` array cards.append(Card.init(coord: Coordinate(latitude: gameArray[2], longitude: gameArray[3]), name: "Card1", threeWords: "london.is.great")) cards.append(Card.init(coord: Coordinate(latitude: gameArray[2], longitude: gameArray[3]), name: "Card2", threeWords: "cheese.is.yummy")) } That's where your data is set up. It contains two cards right now, but you can expand it however you want. Now you need to loop through those cards so you can add them to the UI, so in your ContentView find this line towards the top: @ObservedObject private var card: Card = cards.first(where: { $0.name == "Card1" }) ?? Card.emptyCard You don't need it anymore so you can delete it, or you can leave it there for reference and simply comment it out if you like. Change your VStack to this: ForEach(cards, id: \.self) { card in VStack { CoordEntryView(isLatitude: true, card: card) Divider() CoordEntryView(isLatitude: false, card: card) Divider() TextEntryView_ThreeWords(card: card) } .padding() } What you're doing there is putting the VStack inside a ForEach loop. ForEach simply runs through the items in the cards array, and each item is then referred to as card (where it says card in). In order to use ForEach, your Card class has to be changed to be Hashable. It is changed to become this: class Card: ObservableObject, Hashable { // Note: Hashable added here var uid = UUID().uuidString @Published var coord: Coordinate @Published var name: String @Published var threeWords: String static func == (lhs: Card, rhs: Card) -> Bool { return lhs.uid == rhs.uid } func hash(into hasher: inout Hasher) { hasher.combine(uid) } init(coord: Coordinate, name: String, threeWords: String) { self.coord = coord self.name = name self.threeWords = threeWords } /* 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: "", threeWords: "") } Basically, you add a unique identifier: var uid = UUID().uuidString and you add a couple of methods that make it hashable. Now, when you run the app, you should see both cards in the UI:
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
Okay, I see what you're doing. The CoordEntryView is to be used solely for entering coordinates. You should create a separate view that deals with different input requirements. I've changed the Card class to rename city, which was just an example variable, to threeWords: class Card: ObservableObject { @Published var coord: Coordinate @Published var name: String @Published var threeWords: String init(coord: Coordinate, name: String, threeWords: String) { self.coord = coord self.name = name self.threeWords = threeWords } /* 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: "", threeWords: "") } Then, because it's used in createData() in the main app: 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", threeWords: "london.is.great")) cards.append(Card.init(coord: Coordinate(latitude: gameArray[2], longitude: gameArray[3]), name: "Card2", threeWords: "cheese.is.yummy")) } Then, in the ContentView I've added a new struct: struct TextEntryView_ThreeWords: View { @ObservedObject var card: Card @State private var valueOk: Bool = true var body: some View { TextField("Enter value", text: $card.threeWords) .multilineTextAlignment(.center) .font(.system(size: 36)) .frame(maxWidth: 300) .background( RoundedRectangle(cornerRadius: 8) .fill(Color.blue.opacity(0.15)) ) .onAppear(perform: { checkValue() }) .onChange(of: card.threeWords) { checkValue() } if(!valueOk) { Text("3 lowercase words separated with a full-stop, e.g.: monkey.cheesecake.button") .foregroundStyle(.red) } } private func checkValue() { // Lowercase the String card.threeWords = card.threeWords.lowercased() // This line splits the value entered into an Array of Strings let entered = card.threeWords.lowercased().split{ $0 == "." }.map(String.init) // And this line simply checks whether there are three elements (words) in the array valueOk = (entered.count == 3) } } And to use it, I've added it into the VStack like this: VStack { // In order to reduce duplicated code, I moved the TextField and related stuff into its own View struct CoordEntryView(isLatitude: true, card: card) Divider() CoordEntryView(isLatitude: false, card: card) Divider() TextEntryView_ThreeWords(card: card) } .padding() And it looks like this:
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Fgima Design to SiwftUI PlugIn from Apple
Sigma is a third-party tool. Each time Figma changes something, Apple would have to update their converter. Not gonna happen. It makes more sense for Sigma to write their own converter. Aside from that, this isn't the place for something like this. These are the Developer Forums, where developers of apps for Apple's platforms ask each other for hints and tips on coding.
Topic: Design SubTopic: General
May ’25
Reply to Checking the contents of a TextField variable method not working
No problem. I hope it helps you to learn a little more Swift and SwiftUI. I've given you a few extra concepts that you might be able to use in your own code. I think the important ones are: Running functions when an app starts: init() within your @main entry point. Using classes and splitting them out where appropriate: splitting Coordinate into its own class. Putting things that are specific to a class within the class itself: the validate() function in Coordinate. Trying to cover all possibilities when you're working on something: the different ways we handle the minus sign in the validate() function. Reusing code: creating the CoordEntryView struct that we can reuse for both latitude and longitude. I am by no means a genius with Swift and SwiftUI. I get things wrong, and I still have to ask questions of others. Don't be afraid to ask further questions on these forums. We're quite nice people! Good luck with your code!
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
Reply to Checking the contents of a TextField variable method not working
// ContentView.swift import SwiftUI struct ContentView: View { // This gets the first card where the name property is "Card1" @ObservedObject private var card: Card = cards.first(where: { $0.name == "Card1" }) ?? Card.emptyCard var body: some View { VStack { // In order to reduce duplicated code, I moved the TextField and related stuff into its own View struct CoordEntryView(isLatitude: true, card: card) Divider() CoordEntryView(isLatitude: false, card: card) } .padding() } } struct CoordEntryView: View { var isLatitude: Bool // Allows us to use this same code for the two different coorindates @ObservedObject var card: Card @State private var valueOk: Bool = true var body: some View { Text(isLatitude ? "Latitude" : "Longitude") .bold() TextField("Enter value", text: (isLatitude ? $card.coord.latitude : $card.coord.longitude)) .multilineTextAlignment(.center) .font(.system(size: 36)) .frame(maxWidth: 300) .background( RoundedRectangle(cornerRadius: 8) .fill(Color.blue.opacity(0.15)) ) .onAppear(perform: { checkCoords() }) .onChange(of: (isLatitude ? card.coord.latitude : card.coord.longitude)) { checkCoords() } if(!valueOk) { Text(Coordinate.formatIncorrect) .foregroundStyle(.red) } } private func checkCoords() { // Checks the coordinate value is valid, removes irrelevant characters, makes sure the minus sign is at the beginning, and trims to the right length if(isLatitude) { valueOk = (card.coord.latitude.wholeMatch(of: /^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$/) != nil) card.coord.latitude = Coordinate.validate(card.coord.latitude) // Trim to the right length card.coord.latitude = String(card.coord.latitude.prefix((card.coord.latitude.prefix(1) == "-" ? 10 : 9))) } else { valueOk = (card.coord.longitude.wholeMatch(of: /^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$/) != nil) card.coord.longitude = Coordinate.validate(card.coord.longitude) // Trim to the right length card.coord.longitude = String(card.coord.longitude.prefix((card.coord.longitude.prefix(1) == "-" ? 11 : 10))) } } } #Preview { ContentView() }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’25
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