1

I have an array of values. I want to change it inside the closure. In this closure, I will iterate through the array and initialize the Picker with the binding to every element.

Using this code, I can mutate the values in the array with the help of Picker. Every time I click Picker and change something- It will update the corresponding element in the array.

This example from Apple Docs gives me a warning. "Inferred projection type ... is not a property wrapper".

Error description

struct ContentView: View {
    @EnvironmentObject private var model: Model
    @State private var courses = CodingCourse.exampleData
    @State private var selectedCourse: CodingCourse?
    
    var body: some View {
        NavigationStack {
            List(courses, selection: $selectedCourse) { course in
                Text(course.name)
            }
            .navigationTitle("Coding Courses")
        }
        .searchable(text: $model.searchText, tokens: $model.tokens) { $token in
            Picker(selection: $token.hydration) {
                ForEach(FruitToken.Hydration.allCases) { hydration in
                    switch hydration {
                    case .hydrated: Text("Hydrated")
                    case .dehydrated: Text("Dehydrated")
                    }
                }
            } label: {
                switch token.kind {
                case .apple: Text("Apple")
                case .pear: Text("Pear")
                case .banana: Text("Banana")
                }
            }
        }
    }
}

struct FruitToken: Identifiable, Hashable, CaseIterable {
    static var allCases: [FruitToken] = [FruitToken(kind: .apple), FruitToken(kind: .pear), FruitToken(kind: .banana)]
    
    enum Kind {
        case apple
        case pear
        case banana
        var id: Self { self }
    }
    
    enum Hydration: String, Identifiable, Hashable, CaseIterable {
        var id: Self { self }
        
        case hydrated
        case dehydrated
    }
    
    var kind: Kind
    var hydration: Hydration = .hydrated
    var id: Self { self }
}

class Model: ObservableObject {
    @Published var searchText: String = ""
    @Published var tokens: [FruitToken] = []
    @Published var suggestions: [FruitToken] = FruitToken.allCases
}

struct CodingCourse: Identifiable, Hashable {
    let id = UUID()
    let name: String
}

extension CodingCourse {
    static var exampleData: [CodingCourse] {
        [
            .init(name: "Mastering SwiftUI 3"),
            .init(name: "DisneyPlus Clone in SwiftUI"),
            .init(name: "Drawing App in SwiftUI"),
            .init(name: "Speech ToDo in UIKit"),
            .init(name: "Build Strava Clone in UIKit"),
            .init(name: "Build Music Player")
        ]
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

What's is wrong with this example? How to fix errors? Is it possible to use binding to property inside the closure?

Due to the lack of documentation on performing a search operation and using searchable(text:tokens:placement:prompt:token:) method - any assistance you can provide would be greatly appreciated! :)

Vitya Shurapov
  • 2,200
  • 2
  • 27
  • 32
  • You have two errors that I can see. First, your .searchable should be `.searchable(text: $model.searchText, tokens: $model.tokens) { token in` `token` without the `$`. Second, you have not supplied the `Picker` `selection` with a state variable to keep track of the choice. You are feeding it an enum. – Yrb Jul 09 '23 at 01:31
  • I'm following the example from the official Apple doc. You noticed exactly the right things. I see this syntax first. The goal is to edit the search token. A searchable modifier iterates through tokens and passes them one by one as a parameter to the view builder closure that creates a view given an element in tokens. And with that logic, this $ sign creates some sort of @State property for editing token further in the closure body through the binding. But it doesn’t work as supposed to. – Vitya Shurapov Jul 26 '23 at 16:50

0 Answers0