Post

Replies

Boosts

Views

Activity

Reply to WebView UIViewRepresentable navigationDelegate not getting called
You are setting the web view's navigationDelegate property from within one of the delegate's own methods. The delegate can't call that function because it hasn't been assigned to and doesn't know your implementation exists. Assign your delegates when you create the view, like in the makeUIView(context:) method. func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() webView.uiDelegate = context.coordinator webView.navigationDelegate = context.coordinator return webView } Now the delegate knows the functions to call and you should see your print statement appear in the console.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’23
Reply to Drawing a Pie without Path?
You can override the default Animatable implementation for Shape and provide your own for your custom pie slice. One small problem, however, is that Animatable requires the value(s) to be animated conform to VectorArithmetic. You are using the Angle type which does not conform. You can either add the conformance yourself, or use a type that does conform, such as Double. Here is an example that animates changes to the pie slice correctly: struct ContentView: View { @State private var amount = 0.0 var body: some View { PieSlice(start: -90, end: amount) .fill(.pink) .onTapGesture { withAnimation { amount += 30 } } } } struct PieSlice: Shape { var start: Double var end: Double var animatableData: AnimatablePair<Double, Double> { get { .init(start, end) } set { start = newValue.first end = newValue.second } } func path(in rect: CGRect) -> Path { var path = Path() let center = CGPoint(x: rect.midX, y: rect.midY) path.move(to: center) path.addArc(center: center, radius: rect.midX, startAngle: .degrees(start), endAngle: .degrees(end), clockwise: false) return path } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’23
Reply to Pass a styling as a parameter of a @ViewBuilder function, how?
I tried your code with some test examples but I got a different error. However, it was related to the fact the the parameter of the closure in EnumToShape is of type any HasNormalizedAABB. SwiftUI cannot work with that as it's not a specific type of view: it's any kind of view. A workaround, or solution, would be to create a new wrapper type that conforms to HasNormalizedAABB, and hence View, that can wrap any kind of HasNormalizedAABB. Here is an example implementation: struct AnyHasNormalizedAABB: HasNormalizedAABB { private let wrapped: any HasNormalizedAABB init(_ wrapped: any HasNormalizedAABB) { self.wrapped = wrapped } func normalizedAABB() -> CGRect { wrapped.normalizedAABB() } func path(in rect: CGRect) -> Path { wrapped.path(in: rect) } } @ViewBuilder func EnumToShape( enumState: VisibleShape, transform: @escaping (AnyHasNormalizedAABB) -> some View ) -> some View { switch enumState { case .A: transform(.init(ShapeA())) case .B: transform(.init(ShapeB())) case .C: transform(.init(ShapeC())) case .D: transform(.init(ShapeD())) case .E: transform(.init(ShapeE())) case .F: transform(.init(ShapeF())) } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’23
Reply to Why @Bindable and not @Binding in SwiftUI for iOS 17
I think you're getting confused with all the property wrappers now that iOS 17 and the Observation framework have been introduced. I can give you a quick run down of what each of them do now. ‎ State Use to create a single source of truth for a given value type in a view. Shouldn't be used for reference types as SwiftUI won't update the view when one of its properties changes. @State private var isFavorite = false // Bool is a value type Toggle("Favorite", isOn: $isFavorite) // access the Binding value through $ prefix ‎ Binding Use to create a two-way connection between a property that stores data and a view that displays and changes the data. It connects a property to a source of truth stored elsewhere instead of storing data directly. @Binding var isFavorite: Bool Toggle("Favorite", isOn: $isFavorite) // access the underlying Binding value through $ prefix Would be passed in from parent like so: @State private var isFavorite = false ToggleView(isFavorite: $isFavorite) // expects a Binding so give it one using the $ prefix ‎ Environment Use to read a value stored in a view's environment: An EnvironmentValues environment value @Environment(\.colorScheme) private var colorScheme: ColorScheme A type conforming to the Observable protocol. @Observable final class Profile { var name: String init(name: String) { self.name = name } } @Environment(Profile.self) private var profile: Profile ‎ Bindable Use to create bindings to mutable properties of a data model object that conforms to the Observable protocol. // Can be applied to an initialised new instance @Bindable private var profile = Profile(name: "John Doe") // Can be applied to a parameter property // This acts as a standard property and the value is passed as an argument as normal @Bindable var profile: Profile TextField("Name", text: $profile.name) // Binding object can be extracted with the help of Bindable Can also be used in conjunction with Environment: @Environment(Profile.self) private var profile: Profile @Bindable var profile = profile // must be placed in view body TextField("Name", text: $profile.name) // Binding object can be extracted with the help of Bindable ‎ No Property Wrapper Use for constant properties or similar let viewWidth = 300.0 Use for storing an instance of a type conforming to the Observable protocol. // Can be as an initialisation of a new instance let profile = Profile(name: "John Doe") // Can be as a parameter property let profile: Profile SwiftUI will automatically update the view body when any of the observed values changes. No need for a property wrapper here: it's all done behind the scenes. So, to answer your original question, Binding and Bindable are two completely different property wrappers used for different purposes. Binding is used for reading and writing a value owned by a source of truth, whereas Bindable is used only to create bindings from the properties of observable objects. You can check out the documentation for more information: State Binding Environment Bindable and also watch the WWDC23 session video Discover Observation in SwiftUI.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to Why @Bindable and not @Binding in SwiftUI for iOS 17
Ok. This explanation helps more with where your thinking's at. First of all, after doing some testing, you are correct in saying @State and @Binding now work with reference types. This seems a little strange to me as in the earlier betas I tried this and views weren't being updated (what I thought should happen). So maybe something has changed since then, I'm not sure. It does however make @Bindable sort of in a strange place as bindings can just be extracted from State or Binding. Hopefully, the documentation can be updated to show what property wrapper needs to be used for what, because at the moment it seems like they all do similar things now. ‎Secondly: and just changed the name of @ObservedObject into @Bindable This isn't technically true. @ObservedObject was needed regardless in order for SwiftUI to watch the model object's properties for changes. Now SwiftUI can watch for changes without a property wrapper, and more efficiently too: only when properties that are accessed change will the view be reloaded. @Bindable is more of an attachment to the model allowing binding creation. I don't think it does anything regarding observation itself.
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
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 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 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 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