Post

Replies

Boosts

Views

Activity

Reply to SwiftUI on macOS: double tap on list item
In macOS Ventura, a new modifier, contextMenu(forSelectionType:menu:primaryAction:), was introduced to allow for a primary action to executed in selection-based containers along with the standard context menu. List(selection: $selectedItem) { ... } .contextMenu(forSelectionType: String.self, menu: { _ in }) { // double tap action } Single tap selection still works as well as the double tap action (specific to macOS). There was a contextAction(forSelectionType:action:) modifier originally which was removed and merged with the context menu one. I'm not sure why but it does mean you have to pass in an empty closure to the menu parameter if you want the same functionality.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Error: "'async' call in an autoclosure that does not support concurrency"
Your QuotesViewModelImpl.init is marked as being async, and this is causing the issue. When you create your vm property, you are using the StateObject property wrapper which is initialised with this: init(wrappedValue thunk: @autoclosure @escaping () -> ObjectType) // ObjectType ends up being your QuotesViewModelImpl QuotesViewModelImpl needs to be initialised asynchronously, but in a place that doesn't support concurrency – no async – so you can't use that initialiser. Since there is nothing in that initialiser that needs to be executed asynchronously (i.e. called with await), I suggest you remove the async.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to How to open settings programmatically in Swift
You can access your app's settings page URL from the UIApplication.openSettingsURLString property. Use it like this: Button("Open Settings") { // Get the settings URL and open it if let url = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(url) } } There is currently no way to deep link directly to your app's location settings. iOS 16 did, however, introduce a UIApplication.openNotificationSettingsURLString property for the notifications settings section, so maybe the location settings URL is possible in the future, or through this.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to How to disable multiple TapGestures from being recognized simultaneously in SwiftUI
New in iOS 16 is a contextMenu(forSelectionType:menu:primaryAction:) modifier which accepts a primaryAction closure that is run, for example, when the user taps on a list row. You do, however, need to bind your list's selection value to a stored @State property. Can can use it like this: @State private var selectedNum: Int? List(selection: $selectedNum) { ForEach(1..<10) { i in Text("Hello, world!") } } .contextMenu(forSelectionType: Int.self, menu: { _ in }) { nums in print("Tapped: \(nums.first)") }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to What is the bar in Apple Music called in SwiftUI to switch between "Apple Music" and "Your Library"?
This is actually a feature that comes with searching called search scopes. In SwiftUI, you would combine the searchable(text:placement:prompt:) modifier with searchScopes(_:scopes:) to achieve this effect. Here's an example of how you would use it: @State private var searchText = "" @State private var selectedScope = "Option 1" let allScopes = ["Option 1", "Option 2", "Option 3"] ... .searchable(text: $searchText, prompt: "Search for something") .searchScopes($selectedScope) { ForEach(allScopes, id: \.self) { scope in Text(scope) } } Check out the documentation for each modifier, and I would highly recommend reading this article for more on searching in SwiftUI.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to Merge An Array Item's Array Property Based On Property
So, you have an array of City objects, each with a name and an array of Business objects. You want to have it so that cities with the same name (duplicates) are merged together, along with their businesses. Example: let business1 = Business(name: "Business 1") let business2 = Business(name: "Business 2") let business3 = Business(name: "Business 3") let business4 = Business(name: "Business 4") // before let cities = [ City(name: "City 1", businesses: [business1, business2]), City(name: "City 2", businesses: [business1, business2]), City(name: "City 1", businesses: [business3, business4]) ] // after let cities = [ City(name: "City 1", businesses: [business1, business2, business3, business4]), City(name: "City 2", businesses: [business1, business2]) ] If this is correct, then we can keep going. Something like this can work: // make City Equatable using only its name // this is how the example differentiates between two cities struct City: Equatable { ... static func == (lhs: City, rhs: City) -> Bool { lhs.name == rhs.name } } // this is the cities array without duplicate cities and with merged businesses let newCities: [City] = cities.reduce([]) { result, city in     var newResult = result     if let index = result.firstIndex(of: city) { // gets messy with optionals         newResult[index].businesses?.append(contentsOf: city.businesses ?? [])     } else {         newResult.append(city)     } return newResult } Hopefully, this will work for your use case.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’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:
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