Post

Replies

Boosts

Views

Activity

Reply to NavigationSplitView crashes in Xcode, iOS Beta 7
From the iOS & iPadOS 17 Beta 8 Release Notes: SwiftUI Known Issues On iOS, using an Observable object’s property as a selection value of a List inside NavigationSplitView may cause a “Simultaneous accesses to …” error when a list selection is made via tap gesture. (113978783) Workaround: There is no current workaround for Observable properties. Alternatives include factoring out the selection value into separate state stored outside the object, or using ObservableObject instead. Your best bet is to wait for the next beta (or RC) and try again with that. I would only use the workaround if you need a fix right now.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to how to assign textField's default value in list (swiftUI)
attValue = isEnableBatch ? "batch Enable" : "\(index)" This line cannot be placed inside of a view. It alters the state of the view whilst it is being rendered, which could caused it to re-render infinitely. It must be placed somewhere else, like a closure inside of a view. You can either place it in the button's action just after you toggle the boolean value: Button { isEnableBatch.toggle() attValue = isEnableBatch ? "batch Enable" : "\(index)" // update text field text } label: { ... } or place it in an onChange modifier: .onChange(of: isEnableBatch) { newValue in attValue = newValue ? "batch Enable" : "\(index)" // update text field text whenever boolean changes }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to View won't update in ForEach loop
The problem you have is you're updating the local thing variable when the increment button is tapped. The thing variable is a copy of product.price and so changes to thing will not be reflected elsewhere. This is what the @State property wrapper is used for: to update the view's body when it's underlying value changes. As you already have a state property, base, you can extract read/write values that can be updated from within the view body and will have the behaviour you are expecting. You can use the ForEach initialiser that takes a binding to a collection and gives you a binding to each of its elements to work with. Here is an example that works: ForEach($base) { $product in // `product` is a variable HStack { Text(product.name) Spacer() Button { product.price += 1 } label: { Image(systemName: "plus") } Text("\(product.price, specifier: "%.2f")") } } Just a note on this code: $product is of type Binding<Product>. It provides a way of reading and writing to another value, in this case an element of the base collection. It can be useful if, for example, you have a Stepper control which requires a binding to update its value to and from. product is of type Product. This is a variable and can be read and written to. It also updates the view body when it changes which is why it is useful here.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to Is it possible to color a LineMark based on if it is above or below a certain value?
What do you want colouring, the whole line the same color or segments of the line different colours? You can colour individual points on the line differently, but separate segments I'm not sure about. I think the line can only be one colour. Anyway, if you wanted different segments it might look a bit odd as they're supposed to be transitions to other points. Saying that, you could use a gradient but I don't know if that's what you're looking for.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to How to use the .onMove SwiftUI modifier to reorder SwiftData elements?
One way to do this is to have a property in the model that stores the relative order index. Start by adding this property to the model class: var orderIndex: Int This will need to be added to the initialiser as well. When querying for a list of items, you can sort by this property: @Query(sort: \ChecklistItem.orderIndex) private var items: [ChecklistItem] For the view's move action you can do this: .onMove { source, destination in // Make a copy of the current list of items var updatedItems = items // Apply the move operation to the items updatedItems.move(fromOffsets: source, toOffset: destination) // Update each item's relative index order based on the new items // Can extract and reuse this part if the order of the items is changed elsewhere (like when deleting items) // The iteration could be done in reverse to reduce changes to the indices but isn't necessary for (index, item) in updatedItems.enumerated() { item.orderIndex = index } } That last part I would put in an extension like so: extension [ChecklistItem] { func updateOrderIndices() { for (index, item) in enumerated() { item.orderIndex = index } } } and you can instead write this for better ease of use and reusability: items.updateOrderIndices() // run after changes to the order of `items` When you add a new item, you will need to provide a value for its orderIndex property. This would be resolved as the number of current items (as indexing starts at 0). So if there are 5 items (with indices 0, 1, 2, 3, 4), the new index would be 5. Here's an example of how to do that: // Fetch the number of all items that contribute to the relative index ordering let descriptor = FetchDescriptor<ChecklistItem>(/* add filtering or sorting if needed */) let count = (try? modelContext.fetchCount(descriptor)) ?? 0 // Pass the next index to the new item let newItem = ChecklistItem(..., orderIndex: count) modelContext.insert(newItem) This is only a basic solution and probably isn't the most optimised as any change, even to a single item, results in all the items being updated. Hope it helps anyway!
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to How do you create an inverse relationship to the same model in SwiftData
You need to add another property that can be used for the inverse relationship. You don't have to use this property, it's just to satisfy SwiftData's relationship requirements. For example: @Model final class Person { var name = "" @Relationship(inverse: \Person.parent) var children: [Person]? @Relationship var parent: Person? // can make private if not using elsewhere }
Aug ’23
Reply to SwiftData crashes the app on iOS Beta 6
According to the iOS & iPadOS 17 Beta 7 Release Notes: SwiftData Resolved Issues Fixed in beta 7: Apps using SwiftData that are built with Xcode 15 beta 6 have known issues when running on iOS 17 beta 6. (113915428) New builds with the new Xcode beta should not run into those issues.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to App crashes because of SwiftData
According to the iOS & iPadOS 17 Beta 7 Release Notes: SwiftData Resolved Issues Fixed in beta 7: Apps using SwiftData that are built with Xcode 15 beta 6 have known issues when running on iOS 17 beta 6. (113915428) New builds with the new Xcode beta should not run into those issues.
Topic: Programming Languages SubTopic: Swift Tags:
Aug ’23
Reply to DisclosureGroup with Swipe Actions and Contextual Menu
You can apply the context menu to the label of the disclosure group instead of the whole thing. Something like this works: DisclosureGroup { VStack { Text("1") Text("2") Text("3") } } label: { Text(fruit.rawValue) .contextMenu { Button("Hello", action: { }) } } You will have to long press on the text itself to show the context menu instead of anywhere on the row. You can just change the bounds of the text label if you want that behaviour.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to Parsing a JSON Array Response into SwiftUI View
The first thing you should do is check for any errors and, if so, what they are. Looking at your code, you aren't actually catching any potential errors if they are thrown. You are combining two different approaches: do-catch and if-let. Use one. I suggest changing your code to this: do { let (data, _) = try await URLSession.shared.data(from: url) let decoded = try JSONDecoder().decode([DictionaryWord].self, from: data) { results = decoded } catch { print(error.localizedDescription) } I have also changed the print statement here which will give your more information on what the error is about. For example: the data is corrupted, a key is not found, a value is not found, or even a type mismatch. You can check the error against the cases listed in DecodingError. At this point, I decided to test your code out because it all looked ok and the JSON data at the URL was definitely there. With a more thorough set of catch statements, I found out what the issue was. Firstly, just something to remember, when retrieving data from an API, you need to know what to expect back. In the case of JSON data, what are the keys, value types, and data structures represented. Your data models in code are expecting a set of keys to be present in the JSON data. However, in the data your are receiving some of those keys don't exist. For the URL you have provided these keys aren't in the JSON: DictionaryWord.phonetic, DictionaryWord.origin, Definition.example, Phonetic.text. For other words in the dictionary, their JSON data could be different and be missing other keys, or have all the keys and more. This is why you need to learn about the data you are expecting and is why you aren't able to decode the data with your current approach. As a solution, you can either remove the missing keys directly from the data models, or mark them as optional so that the decoder knows they might not be present (preferable).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to iOS 17 beta, searchable suggested tokens disappear when query is not empty
From the iOS & iPadOS 17 Beta Release Notes: SwiftUI Resolved Issues Fixed: Suggested search tokens will be hidden by default when the search text is not empty (108381393) It seems like this behaviour is the default: only show the suggested tokens before the user starts typing. If you want an alternative solution (not really a workaround as you can't change the default behaviour), you can show your own custom suggested tokens as buttons, and when pressed are added to the tokens array. Here's an example of what it could look like: struct ContentView: View { @State private var query = "" @State private var tokens: [Token] = [] @State private var isSearching = false private let suggestions = [Token(text: "One"), Token(text: "Two")] var body: some View { NavigationStack { List { ... } .overlay { if isSearching { // put here whatever condition you need to show the suggested tokens List(suggestions) { suggestion in Button(suggestion.text) { tokens.append(suggestion) } } } } .navigationTitle("Search Suggestions") .searchable(text: $query, tokens: $tokens, isPresented: $isSearching, placement: .toolbar, prompt: "Search") { token in Text(token.text) } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23