Post

Replies

Boosts

Views

Activity

Reply to Nothing Happens When Rotating An Image With Animation
You have to tell SwiftUI when and what to animate. Currently, you have a static symbol image that has been rotated 360°, but hasn't been told to animate. Applying the animation(_:value:) modifier doesn't start the animation; it just tells SwiftUI what animation to do when the value changes. Something like this should work: @State private var rotationAngle: Double = 0 var body: some View {     HStack {         Image(systemName: "arrow.clockwise")             .rotationEffect(.degrees(rotationAngle))             .animation(.linear(duration: 1.5).repeatForever(autoreverses: false), value: rotationAngle)         Text("Downloading ...")     }     .onAppear {         rotationAngle = 360     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Saved strings don't save when app closes
Your File 1 and File 2 code seems to be disconnected as the variable names are different, so either you have modified the code or haven't show all of it. When you write this line, are you sure File1.text and File1.text2 are both strings that can be converted into a Double (a number)?: if let longitude = Double(File1.text), let latitude = Double(File1.text2) { If these values are simple strings, like "Hello", and not a string of a number, like "10.5", then the above line of code will fail and everything inside of the if statement will not be run. Here is an example of what you could to instead which would make sure the latitude and longitude values are both numbers and not random strings: You can use the @AppStorage property wrapper to automatically read and write a value to UserDefaults. You can then use the TextField initialiser that accepts a number as a binding and will automatically handle the conversion between String and Double for you. You can then use these Double values straight away and pass them to CLLocation without any problems with optionals and String-Double conversion. @AppStorage("latitude") private var latitude: Double = 0 @AppStorage("longitude") private var longitude: Double = 0 TextField("Latitude", value: $latitude, format: .number) TextField("Longitude", value: $longitude, format: .number) // add this modifier to text fields to only allow numbers to be entered .keyboardType(.decimalPad) // this will work always so use wherever CLLocation(latitude: latitude, longitude: longitude) Hopefully this helps and points you to a better solution.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Beginner question in XCode "Cannot convert value of type 'String' to expected argument type 'NSNotification.Name?'"
You have defined updateShoppingList so that its function signature is updateShoppingList(notification:), but then you are trying to use it as updateShoppingList(_:) in the selector. You will need to change it to this: #selector(updateShoppingList(notification:)) or more commonly and simpler: #selector(updateShoppingList) Also, when you write this: NotificationCenter.default.addObserver(self, selector: #selector(updateShoppingList), name: .kShoppingChanged, object: nil) you are saying that the method self.updateShoppingList exists and can be run. Make sure you have your methods in the right place.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Reverse animation in swiftUI
This seems like a trivial problem with a simple solution but the way SwiftUI handles the animation and the repeatForever(_:autoreverses:) method makes it more effortful. The `repeatCount a parameter requires an odd number to prevent the strange “jumps”, and using either of the values 1 and 3 result in no fix. The solution I found was to create two separate animations, one delayed after the other. withAnimation { isAnimated = true withAnimation(.default.delay(0.4)) { // play with delay to see what feels right isAnimated = false } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Why does custom Binding not update UI
Why can't you add the ObservableObject protocol conformance? It only really affects the properties that are marked with the @Published property wrapper, i.e. the properties that update the UI. This is what allows SwiftUI to update the UI based on properties in a class – it is the recommended way. class BoolWrapper: ObservableObject { @Published var value = false {     didSet {       print("Value changed to \(value)")     }   } } struct ContentView: View { @StateObject private var boolWrapper = BoolWrapper()   var body: some View {     Toggle("Toggle", isOn: $boolWrapper.value)   } } The UI can't update if it doesn't watch for changes from inside a class. That is why ObservableObject exists in SwiftUI. If it was a struct, you would only need to use an @State property due to the nature of structs (vs classes).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Why does custom Binding not update UI
Thank you for mentioning that. I guess a different approach to this would be storing the boolean value as a local @State variable and manually changing this. Something like this will work: @State private var boolValue = false init() {     _boolValue = State(initialValue: boolWrapper.value) } var body: some View {     Toggle(boolValue ? "Toggle On" : "Toggle Off", isOn: $boolValue)         .onChange(of: boolValue) { newValue in             boolWrapper.value = newValue         } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Picker the selection "" is invalid and does not have an associated tag, this will give undefined results
You have provided to the Picker the selectOption array as its available selection values. You have set the initial selection value to be an empty string which is not in the selectOption array. You need to specify an initial value that is in the array for the console message to go away. @State var fieldValue: String = "1" // any of the values in selectOption You can also set the selection binding to be an optional string, but then you will get this console message: Picker: the selection "nil" is invalid and does not have an associated tag, this will give undefined results.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to How to hide an arrow inside List with NavigationLink?
There is currently no modifier to do this. SwiftUI doesn't have much in the way of customising list row accessories (I have previously filed feedback for this). The easiest way to get around this would be to use a Button instead and manually perform the navigation; the APIs in iOS 16 make this much easier. For example: @State private var path = NavigationPath() NavigationStack(path: $path) { List(newsList) { article in    Button { path.append(article) } label: {        NewsCell(news: article)    } } .navigationDestination(for: Article.self) { article in NewsLetterView(news: article) } } There are some other hacky workarounds that you can find doing an online search, so you can go with that as well until a new modifier is released (iOS 17?).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to How to dismiss a Sheet and open a NavigationLink in a new View?
It's quite difficult to understand what is happening if you don't, at least, provide some code alongside your explanation. It then wouldn't require us to guess what your current situation looks like. Here's something that works using example data (according to my interpretation of your question): struct ContentView: View {     @State private var path: [Int] = []     @State private var showingSheet = false     var body: some View { // use the path of the NavigationStack to allow for programmatic navigation         NavigationStack(path: $path) {             Text("Hello, World!")                 .navigationDestination(for: Int.self) { num in                     Text("Detail \(num)")                 }             .toolbar {                 Button("Search") {                     showingSheet = true                 }             }             .sheet(isPresented: $showingSheet) {                 SearchView(path: $path)             }         }     } } struct SearchView: View {     @Environment(\.dismiss) private var dismiss     @Binding var path: [Int]     var body: some View {         List(1...10, id: \.self) { num in             Button("Option \(num)") { // dismiss the sheet and then navigate to the selection's corresponding detail view                 dismiss()                 path.append(num)             }         }     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Nov ’22
Reply to weatherKit
The WeatherKit API only needs you to provide a CLLocation object, nothing about the name of a city/country. You will have to use your own list of city/country names and get the locations of these to pass to WeatherKit. Helpfully, CLGeocoder has that functionality already. Here is an example of how to use it: func location(for address: String) async throws -> CLLocation? {     let placemarks = try await CLGeocoder().geocodeAddressString(address)     return placemarks.first?.location } if let londonLocation = try? await location(for: "London") {     // pass londonLocation to WeatherKit     let coordinates = londonLocation.coordinate     print(coordinates) // CLLocationCoordinate2D(latitude: 51.5033466, longitude: -0.0793965) }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Nov ’22
Reply to NavigationSplitView No Toggle Button
Why is there no toggle button above? What do you mean by "toggle button"? Do you mean the button that hides and shows the sidebar? This is only present when the horizontalSizeClass is .regular. On an iPhone in portrait mode, it won't appear. ‎  And why is the menu always showing? What "menu" are you talking about? ‎ I cant see the detiail view anymore If you want to see the detail view, you need to select an item from the list. As I said before, the two-column layout with the sidebar toggle button is only present when the horizontalSizeClass is .regular. In your screenshot (an iPhone in portrait mode) the NavigationSplitView collapses down to a single column layout and acts more like a NavigationStack.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Nov ’22
Reply to Constraint for views in SwiftUI
You can use the Spacer() view which will take up all available space. It will also share this space equally when there are multiple. VStack { ViewA() Spacer() // push ViewA to the top ViewB() // takes up the available space Spacer() // push ViewC to the bottom ViewC() } You could also give ViewB a fixed height but I guess you don't want to do that.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Nov ’22
Reply to Nothing Happens When Rotating An Image With Animation
You have to tell SwiftUI when and what to animate. Currently, you have a static symbol image that has been rotated 360°, but hasn't been told to animate. Applying the animation(_:value:) modifier doesn't start the animation; it just tells SwiftUI what animation to do when the value changes. Something like this should work: @State private var rotationAngle: Double = 0 var body: some View {     HStack {         Image(systemName: "arrow.clockwise")             .rotationEffect(.degrees(rotationAngle))             .animation(.linear(duration: 1.5).repeatForever(autoreverses: false), value: rotationAngle)         Text("Downloading ...")     }     .onAppear {         rotationAngle = 360     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Saved strings don't save when app closes
Your File 1 and File 2 code seems to be disconnected as the variable names are different, so either you have modified the code or haven't show all of it. When you write this line, are you sure File1.text and File1.text2 are both strings that can be converted into a Double (a number)?: if let longitude = Double(File1.text), let latitude = Double(File1.text2) { If these values are simple strings, like "Hello", and not a string of a number, like "10.5", then the above line of code will fail and everything inside of the if statement will not be run. Here is an example of what you could to instead which would make sure the latitude and longitude values are both numbers and not random strings: You can use the @AppStorage property wrapper to automatically read and write a value to UserDefaults. You can then use the TextField initialiser that accepts a number as a binding and will automatically handle the conversion between String and Double for you. You can then use these Double values straight away and pass them to CLLocation without any problems with optionals and String-Double conversion. @AppStorage("latitude") private var latitude: Double = 0 @AppStorage("longitude") private var longitude: Double = 0 TextField("Latitude", value: $latitude, format: .number) TextField("Longitude", value: $longitude, format: .number) // add this modifier to text fields to only allow numbers to be entered .keyboardType(.decimalPad) // this will work always so use wherever CLLocation(latitude: latitude, longitude: longitude) Hopefully this helps and points you to a better solution.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Beginner question in XCode "Cannot convert value of type 'String' to expected argument type 'NSNotification.Name?'"
You have defined updateShoppingList so that its function signature is updateShoppingList(notification:), but then you are trying to use it as updateShoppingList(_:) in the selector. You will need to change it to this: #selector(updateShoppingList(notification:)) or more commonly and simpler: #selector(updateShoppingList) Also, when you write this: NotificationCenter.default.addObserver(self, selector: #selector(updateShoppingList), name: .kShoppingChanged, object: nil) you are saying that the method self.updateShoppingList exists and can be run. Make sure you have your methods in the right place.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Making table header opaque to scrolling rows in SwiftUI
Can you attach an image of what this would look like?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Reverse animation in swiftUI
This seems like a trivial problem with a simple solution but the way SwiftUI handles the animation and the repeatForever(_:autoreverses:) method makes it more effortful. The `repeatCount a parameter requires an odd number to prevent the strange “jumps”, and using either of the values 1 and 3 result in no fix. The solution I found was to create two separate animations, one delayed after the other. withAnimation { isAnimated = true withAnimation(.default.delay(0.4)) { // play with delay to see what feels right isAnimated = false } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Why does custom Binding not update UI
Why can't you add the ObservableObject protocol conformance? It only really affects the properties that are marked with the @Published property wrapper, i.e. the properties that update the UI. This is what allows SwiftUI to update the UI based on properties in a class – it is the recommended way. class BoolWrapper: ObservableObject { @Published var value = false {     didSet {       print("Value changed to \(value)")     }   } } struct ContentView: View { @StateObject private var boolWrapper = BoolWrapper()   var body: some View {     Toggle("Toggle", isOn: $boolWrapper.value)   } } The UI can't update if it doesn't watch for changes from inside a class. That is why ObservableObject exists in SwiftUI. If it was a struct, you would only need to use an @State property due to the nature of structs (vs classes).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Why does custom Binding not update UI
Thank you for mentioning that. I guess a different approach to this would be storing the boolean value as a local @State variable and manually changing this. Something like this will work: @State private var boolValue = false init() {     _boolValue = State(initialValue: boolWrapper.value) } var body: some View {     Toggle(boolValue ? "Toggle On" : "Toggle Off", isOn: $boolValue)         .onChange(of: boolValue) { newValue in             boolWrapper.value = newValue         } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to Picker the selection "" is invalid and does not have an associated tag, this will give undefined results
You have provided to the Picker the selectOption array as its available selection values. You have set the initial selection value to be an empty string which is not in the selectOption array. You need to specify an initial value that is in the array for the console message to go away. @State var fieldValue: String = "1" // any of the values in selectOption You can also set the selection binding to be an optional string, but then you will get this console message: Picker: the selection "nil" is invalid and does not have an associated tag, this will give undefined results.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to How to hide an arrow inside List with NavigationLink?
There is currently no modifier to do this. SwiftUI doesn't have much in the way of customising list row accessories (I have previously filed feedback for this). The easiest way to get around this would be to use a Button instead and manually perform the navigation; the APIs in iOS 16 make this much easier. For example: @State private var path = NavigationPath() NavigationStack(path: $path) { List(newsList) { article in    Button { path.append(article) } label: {        NewsCell(news: article)    } } .navigationDestination(for: Article.self) { article in NewsLetterView(news: article) } } There are some other hacky workarounds that you can find doing an online search, so you can go with that as well until a new modifier is released (iOS 17?).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to How to dismiss a Sheet and open a NavigationLink in a new View?
It's quite difficult to understand what is happening if you don't, at least, provide some code alongside your explanation. It then wouldn't require us to guess what your current situation looks like. Here's something that works using example data (according to my interpretation of your question): struct ContentView: View {     @State private var path: [Int] = []     @State private var showingSheet = false     var body: some View { // use the path of the NavigationStack to allow for programmatic navigation         NavigationStack(path: $path) {             Text("Hello, World!")                 .navigationDestination(for: Int.self) { num in                     Text("Detail \(num)")                 }             .toolbar {                 Button("Search") {                     showingSheet = true                 }             }             .sheet(isPresented: $showingSheet) {                 SearchView(path: $path)             }         }     } } struct SearchView: View {     @Environment(\.dismiss) private var dismiss     @Binding var path: [Int]     var body: some View {         List(1...10, id: \.self) { num in             Button("Option \(num)") { // dismiss the sheet and then navigate to the selection's corresponding detail view                 dismiss()                 path.append(num)             }         }     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22
Reply to weatherKit
The WeatherKit API only needs you to provide a CLLocation object, nothing about the name of a city/country. You will have to use your own list of city/country names and get the locations of these to pass to WeatherKit. Helpfully, CLGeocoder has that functionality already. Here is an example of how to use it: func location(for address: String) async throws -> CLLocation? {     let placemarks = try await CLGeocoder().geocodeAddressString(address)     return placemarks.first?.location } if let londonLocation = try? await location(for: "London") {     // pass londonLocation to WeatherKit     let coordinates = londonLocation.coordinate     print(coordinates) // CLLocationCoordinate2D(latitude: 51.5033466, longitude: -0.0793965) }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22
Reply to Upgrade Swift Playgrounds App to iOS 16
Could you not just create a new empty app and then copy over all of the files and settings?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22
Reply to NavigationSplitView No Toggle Button
Why is there no toggle button above? What do you mean by "toggle button"? Do you mean the button that hides and shows the sidebar? This is only present when the horizontalSizeClass is .regular. On an iPhone in portrait mode, it won't appear. ‎  And why is the menu always showing? What "menu" are you talking about? ‎ I cant see the detiail view anymore If you want to see the detail view, you need to select an item from the list. As I said before, the two-column layout with the sidebar toggle button is only present when the horizontalSizeClass is .regular. In your screenshot (an iPhone in portrait mode) the NavigationSplitView collapses down to a single column layout and acts more like a NavigationStack.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22
Reply to Safely converting optional state to non optional binding
Could you not just do this: // unwrap variable normally if let nonOptional = optional_ { // create new binding using unwrapped value let binding = Binding { nonOptional } set: { optional_ = $0 } ChildView(nonOptional: binding) ... }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22
Reply to Constraint for views in SwiftUI
You can use the Spacer() view which will take up all available space. It will also share this space equally when there are multiple. VStack { ViewA() Spacer() // push ViewA to the top ViewB() // takes up the available space Spacer() // push ViewC to the bottom ViewC() } You could also give ViewB a fixed height but I guess you don't want to do that.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’22