"Searchable" fonctionne bien seul, mais ne filtre plus la recherche, une fois inclus dans mon code.

Bonjour, J'ai un problème avec ma liste. La fonction "searchable" fonctionne très bien lorsque la liste est simple et ne contient ni boutons, ni NavigationLink, mais une fois ceux-ci inclus, la barre de recherche ne filtre plus la liste. Si vous avez une solution... Merci de votre aide !

Answered by Claude31 in 729504022

Voici une version du code qui semble faire ce que tu attends:

Il faudra voir comment calculer les images et les tag, si tu en as besoin quelque part.

import SwiftUI
struct Aubepine: View { // <<-- Pour le test
    
    var body: some View {
        Text("Aubepine")
    }
}

struct Bouleau: View { // <<-- Pour le test
    
    var body: some View {
        Text("Bouleau")
    }
}

struct Charme: View { // <<-- Pour le test
    
    var body: some View {
        Text("Charme")
    }
}

struct Chataignier: View { // <<-- Pour le test
    
    var body: some View {
        Text("Chataignier")
    }
}

struct Chene: View { // <<-- Pour le test
    
    var body: some View {
        Text("Chene")
    }
}

struct Tilleul: View { // <<-- Pour le test
    
    var body: some View {
        Text("Tilleul")
    }
}

struct ListeArbres: View {
    var image : String = ""
    
    @State private var searchText = ""
    
    @State var isOn = false
    
    func test()->Bool {
        return !isOn
    }
    
    var Arbres = [
        "Aubépine",
        "Bouleau",
        "Charme",
        "Châtaignier",
        "Chêne",
        "Tilleul" ]
    
    enum NavigationItem {
        case Aubepine
        case Bouleau
        case Charme
        case Chataignier
        case Chene
        case Tilleul
    }

    func tag(for arbre: String) -> NavigationItem {
        switch arbre {
            case "Aubépine"  : return .Aubepine
            case "Bouleau"   : return .Bouleau
            case "Charme"    : return .Charme
            case "Châtaignier":return .Chataignier
            case "Chêne"     : return .Chene
            case "Tilleul"   : return .Tilleul
            default: return .Aubepine        // To have something
        }
    }

    @State var navigatedItem: NavigationItem?
    
    var filteredNames: [String] {   // <<-- déplacé
        if searchText.isEmpty {
            return Arbres
        } else {
            return Arbres.filter {
                $0.contains(searchText)
            }
            
        }
    }
    
    @ViewBuilder func destination(to arbre: String) -> some View {
        switch arbre {
            case "Aubépine":
                Aubepine()
            case "Bouleau":
                Bouleau()
            case "Charme":
                Charme()
            case "Châtaignier":
                Chataignier()
            case "Chêne":
                Chene()
            case "Tilleul":
                Tilleul()
            default:
                EmptyView()
        }
    }
    var body: some View {
        
        NavigationView {
            
            List (filteredNames, id:\.self) { arbre in
                Group {
                    VStack {
                        NavigationLink(destination: destination(to: arbre), tag: tag(for: arbre), selection: $navigatedItem) { EmptyView() }

                        Button(
                            action: { isOn = test() },
                            label : {
                                HStack (spacing: 50){
                                    Image("aubepine fruit")
                                        .resizable()
                                        .scaledToFit()
                                        .frame( height: 70)
                                        .position(x: 40, y: 30)
                                        .padding(.vertical,4)
                                    
                                    Text(arbre)
                                        .font(.title)
                                        .position(x: -20, y: 30)
                                }
                            })
                    }
                    
                    /* SUPPRIMER
                    VStack {
                        NavigationLink(destination: destination(to: arbre), tag: NavigationItem.Bouleau, selection: $navigatedItem){EmptyView()}
                        Button(
                            action: {
                                // <<-- Quelle est l'action ?
                                print("No action")
                            },
                            label: {
                                VStack { NavigationLink(destination: Tilleul(), tag: NavigationItem.Tilleul, selection: $navigatedItem){EmptyView()}
                                    Button( action: { isOn = test() },
                                            label :{

                                        HStack (spacing: 50){
                                            Image("tilleul feuille")
                                                .resizable()
                                                .scaledToFit()
                                                .frame(height: 70)
                                                .position(x: 50, y: 30)
                                                .padding(.vertical,4)

                                            Text("Tilleul")
                                                .font(.title)
                                                .position(x: -20, y: 30)
                                        }
                                    })
                                }
                            }// <<-- Manque ici ?
                        ) // <<-- Manque ?
                        
                        /* SUPPRIMER VStack {
                        } */
                    
                        .navigationBarTitleDisplayMode(.inline)
                        .buttonStyle(PlainButtonStyle() )
                    }*/
                } .searchable(text: $searchText, prompt: "Chercher")
                    .navigationTitle("Arbres à connaître")
                    .frame(width: 400)
                
            } // End List
            
        }
    }
} // <<-- Manque

struct ListeArbres_Previews: PreviewProvider {
    static var previews: some View {
        ListeArbres()
    }
} // <<-- Manque

Peux tu poster le code, sinon très difficile de trouver la cause…

Bonjour Claude, Je viens d'essayer de passer autrement, mais la chose ne fonctionne toujours pas. Alors Merci Beaucoup pour votre aide. Voici mon code (coupé par rubrique car trop long pour ce post):

//DEBUT:

import SwiftUI

struct ListeArbres: View {

var image : String = ""

      
@State private var searchText = ""
        
@State var isOn = false
        
        func test()->Bool {
            if isOn == false {
                isOn = true
                }else{
                isOn = false
                    }
            return isOn
        }
        
        var Arbres = [
        "Aubépine",
        "Bouleau",
        "Charme",
        "Châtaignier",
        "Chêne",

//SUITE :

"Tilleul" ]

        enum NavigationItem {
        case Aubepine
        case Bouleau
        case Charme
        case Chataignier

//SUITE :

case Tilleul }

        @State var navigatedItem: NavigationItem?
      

        
        var body: some View {
            
            NavigationView {
                
                List (filteredNames, id:\.self) { arbre in
                    
                 
                    
                    Group {
                    VStack {
                        NavigationLink(destination: Aubepine(), tag: NavigationItem.Aubepine, selection: $navigatedItem){EmptyView()}
                    Button(
                        action:{
                           
                         isOn = test()
                            
                        },
                        label :{
                            
                            HStack (spacing: 50){
                            Image("aubepine fruit")
                                .resizable()
                                .scaledToFit()
                                .frame( height: 70)
                                .position(x: 40, y: 30)
                                .padding(.vertical,4)
                            
                  Text("Aubépine")
                      .font(.title)
                      .position(x: -20, y: 30)
                            }
                        })
            
                    }
                    
                    VStack {
                        NavigationLink(destination: Bouleau(), tag: NavigationItem.Bouleau, selection: $navigatedItem){EmptyView()}
                    Button(
                        action:{

//SUITE & FIN :

VStack { NavigationLink(destination: Tilleul(), tag: NavigationItem.Tilleul, selection: $navigatedItem){EmptyView()} Button( action:{

                             isOn = test()
                                
                            },
                            label :{
                                
                                HStack (spacing: 50){
                                Image("tilleul feuille")
                                    .resizable()
                                    .scaledToFit()
                                    .frame(height: 70)
                                    .position(x: 50, y: 30)
                                    .padding(.vertical,4)
                                
                      Text("Tilleul")
                          .font(.title)
                          .position(x: -20, y: 30)
                                }
                            })
                        }
                    
                        VStack {
                          
                        }
                       


                
             
                .navigationBarTitleDisplayMode(.inline)
                
                 .buttonStyle(PlainButtonStyle()
                              )}
                    } .searchable(text: $searchText, prompt: "Chercher")
                        .navigationTitle("Arbres à connaître")
                      
                                
                .frame(width: 400)

            }
    
        }

var filteredNames: [String] {

if searchText.isEmpty {
    return Arbres
}else{
    return Arbres.filter {
        $0.contains(searchText)
    }
    
}

} }

struct ListeArbres_Previews: PreviewProvider { static var previews: some View { ListeArbres() }

// Lorsque ma liste est simple (un text sans bouton, ni navigationLink), le filtre de recherche fonctionne correctement. Mais une fois inclus les boutons et la navigation, le filtre de la searchBar ne renvoie plus rien (elle écrit, mais ne filtre plus).

MERCI BEAUCOUP CLAUDE Christophe

Après une nouvelle journée de recherches et de tests, mon "searchable" a toujours son problème de filtre après implémentation des boutons et des nav. J'ai appris hier que le "searchable" ne fonctionne que sur iOs15 (sur lequel mon code est pourtant construit). Je me pose la question : "vaut-il mieux utiliser "TextField" et créer soi-même son "searchable" ? Qu'en pensez-vous ? Quelqu'un d'autre a-t-il des problèmes avec "searchable" ? Merci de votre réponse !

J'ai essayé de tester.

mais plusieurs erreurs:

  • Use of local variable 'filteredNames' before its declaration
  • Cannot find 'Aubepine' in scope

Il me semble qu'il manque des } dans le code, ou qu'elles sont au mauvais endroit.

J'ai essayé de reconstituer. Est ce cela ?

Je ne comprends pas la logique: List va répéter 6 fois les VStack avec Aubepine et Bouleau… et arbre n'est pas utilisé ?

Plutôt que d'appeler directement Aubepine(), il faut créer un ViewBuilder, qui en fonction de arbre, retournera la bonne view:

import SwiftUI
struct Aubepine: View { // <<-- Pour le test
    
    var body: some View {
        Text("Aubepine")
    }
}

struct Bouleau: View { // <<-- Pour le test
    
    var body: some View {
        Text("Bouleau")
    }
}

struct Tilleul: View { // <<-- Pour le test
    
    var body: some View {
        Text("Tilleul")
    }
}

struct ListeArbres: View {
    var image : String = ""
    
    @State private var searchText = ""
    
    @State var isOn = false
    
    func test()->Bool {
        if isOn == false {
            isOn = true
        } else {
            isOn = false
        }
        return isOn
    }
    
    var Arbres = [
        "Aubépine",
        "Bouleau",
        "Charme",
        "Châtaignier",
        "Chêne",
        "Tilleul" ]
    
    enum NavigationItem {
        case Aubepine
        case Bouleau
        case Charme
        case Chataignier
        case Chene  // <<-- Manque
        case Tilleul
    }
    @State var navigatedItem: NavigationItem?
    
    var filteredNames: [String] {   // <<-- déplacé
        if searchText.isEmpty {
            return Arbres
        } else {
            return Arbres.filter {
                $0.contains(searchText)
            }
            
        }
    }
    var body: some View {
        
        NavigationView {
            
            List (filteredNames, id:\.self) { arbre in
                Group {
                    VStack {
                        NavigationLink(destination: Aubepine(), tag: NavigationItem.Aubepine, selection: $navigatedItem){EmptyView()}
                        Button(
                            action: { isOn = test() },
                            label : {
                                HStack (spacing: 50){
                                    Image("aubepine fruit")
                                        .resizable()
                                        .scaledToFit()
                                        .frame( height: 70)
                                        .position(x: 40, y: 30)
                                        .padding(.vertical,4)
                                    
                                    Text("Aubépine")
                                        .font(.title)
                                        .position(x: -20, y: 30)
                                }
                            })
                    }
                    
                    VStack {
                        NavigationLink(destination: Bouleau(), tag: NavigationItem.Bouleau, selection: $navigatedItem){EmptyView()}
                        Button(
                            action: {
                                // <<-- Quelle est l'action ?
                                print("No action")
                            },
                            label: {
                                VStack { NavigationLink(destination: Tilleul(), tag: NavigationItem.Tilleul, selection: $navigatedItem){EmptyView()}
                                    Button( action: { isOn = test() },
                                            label :{
                                        
                                        HStack (spacing: 50){
                                            Image("tilleul feuille")
                                                .resizable()
                                                .scaledToFit()
                                                .frame(height: 70)
                                                .position(x: 50, y: 30)
                                                .padding(.vertical,4)
                                            
                                            Text("Tilleul")
                                                .font(.title)
                                                .position(x: -20, y: 30)
                                        }
                                    })
                                }
                            }// <<-- Manque ici ?
                        ) // <<-- Manque ?
                        VStack {
                        }
                        .navigationBarTitleDisplayMode(.inline)
                        .buttonStyle(PlainButtonStyle() )
                    }
                } .searchable(text: $searchText, prompt: "Chercher")
                    .navigationTitle("Arbres à connaître")
                
                
                    .frame(width: 400)
                
            }
            
        }
    }
} // <<-- Manque

struct ListeArbres_Previews: PreviewProvider {
    static var previews: some View {
        ListeArbres()
    }
} // <<-- Manque

La fonction test() peut être simplifiée:

    func test()->Bool {
        isOn.toggle()
        return isOn
    }

Mais en fait, il suffit de remplacer

isOn = test()

par

 isOn.toggle()
Accepted Answer

Voici une version du code qui semble faire ce que tu attends:

Il faudra voir comment calculer les images et les tag, si tu en as besoin quelque part.

import SwiftUI
struct Aubepine: View { // <<-- Pour le test
    
    var body: some View {
        Text("Aubepine")
    }
}

struct Bouleau: View { // <<-- Pour le test
    
    var body: some View {
        Text("Bouleau")
    }
}

struct Charme: View { // <<-- Pour le test
    
    var body: some View {
        Text("Charme")
    }
}

struct Chataignier: View { // <<-- Pour le test
    
    var body: some View {
        Text("Chataignier")
    }
}

struct Chene: View { // <<-- Pour le test
    
    var body: some View {
        Text("Chene")
    }
}

struct Tilleul: View { // <<-- Pour le test
    
    var body: some View {
        Text("Tilleul")
    }
}

struct ListeArbres: View {
    var image : String = ""
    
    @State private var searchText = ""
    
    @State var isOn = false
    
    func test()->Bool {
        return !isOn
    }
    
    var Arbres = [
        "Aubépine",
        "Bouleau",
        "Charme",
        "Châtaignier",
        "Chêne",
        "Tilleul" ]
    
    enum NavigationItem {
        case Aubepine
        case Bouleau
        case Charme
        case Chataignier
        case Chene
        case Tilleul
    }

    func tag(for arbre: String) -> NavigationItem {
        switch arbre {
            case "Aubépine"  : return .Aubepine
            case "Bouleau"   : return .Bouleau
            case "Charme"    : return .Charme
            case "Châtaignier":return .Chataignier
            case "Chêne"     : return .Chene
            case "Tilleul"   : return .Tilleul
            default: return .Aubepine        // To have something
        }
    }

    @State var navigatedItem: NavigationItem?
    
    var filteredNames: [String] {   // <<-- déplacé
        if searchText.isEmpty {
            return Arbres
        } else {
            return Arbres.filter {
                $0.contains(searchText)
            }
            
        }
    }
    
    @ViewBuilder func destination(to arbre: String) -> some View {
        switch arbre {
            case "Aubépine":
                Aubepine()
            case "Bouleau":
                Bouleau()
            case "Charme":
                Charme()
            case "Châtaignier":
                Chataignier()
            case "Chêne":
                Chene()
            case "Tilleul":
                Tilleul()
            default:
                EmptyView()
        }
    }
    var body: some View {
        
        NavigationView {
            
            List (filteredNames, id:\.self) { arbre in
                Group {
                    VStack {
                        NavigationLink(destination: destination(to: arbre), tag: tag(for: arbre), selection: $navigatedItem) { EmptyView() }

                        Button(
                            action: { isOn = test() },
                            label : {
                                HStack (spacing: 50){
                                    Image("aubepine fruit")
                                        .resizable()
                                        .scaledToFit()
                                        .frame( height: 70)
                                        .position(x: 40, y: 30)
                                        .padding(.vertical,4)
                                    
                                    Text(arbre)
                                        .font(.title)
                                        .position(x: -20, y: 30)
                                }
                            })
                    }
                    
                    /* SUPPRIMER
                    VStack {
                        NavigationLink(destination: destination(to: arbre), tag: NavigationItem.Bouleau, selection: $navigatedItem){EmptyView()}
                        Button(
                            action: {
                                // <<-- Quelle est l'action ?
                                print("No action")
                            },
                            label: {
                                VStack { NavigationLink(destination: Tilleul(), tag: NavigationItem.Tilleul, selection: $navigatedItem){EmptyView()}
                                    Button( action: { isOn = test() },
                                            label :{

                                        HStack (spacing: 50){
                                            Image("tilleul feuille")
                                                .resizable()
                                                .scaledToFit()
                                                .frame(height: 70)
                                                .position(x: 50, y: 30)
                                                .padding(.vertical,4)

                                            Text("Tilleul")
                                                .font(.title)
                                                .position(x: -20, y: 30)
                                        }
                                    })
                                }
                            }// <<-- Manque ici ?
                        ) // <<-- Manque ?
                        
                        /* SUPPRIMER VStack {
                        } */
                    
                        .navigationBarTitleDisplayMode(.inline)
                        .buttonStyle(PlainButtonStyle() )
                    }*/
                } .searchable(text: $searchText, prompt: "Chercher")
                    .navigationTitle("Arbres à connaître")
                    .frame(width: 400)
                
            } // End List
            
        }
    }
} // <<-- Manque

struct ListeArbres_Previews: PreviewProvider {
    static var previews: some View {
        ListeArbres()
    }
} // <<-- Manque

Merci. Au fait, pour l'image, fais exactement comme pour les tag:

func image(for arbre: String) -> Image {
        switch arbre {
            case "Aubépine"  : return Image("aubepine fruit")
            case "Bouleau"   : return Image("bouleau fruit")
            case "Charme"    : return Image("charme fruit")
            case "Châtaignier":return Image("chataigner fruit")
            case "Chêne"     : return Image("chene fruit")
            case "Tilleul"   : return Image("tilleul fruit")
            default: return Image("")        // To have something
        }
    }

Utilisé ainsi:

                            label : {
                                HStack (spacing: 50){
//                                    Image("aubepine fruit")
                                    image(for: arbre)
"Searchable" fonctionne bien seul, mais ne filtre plus la recherche, une fois inclus dans mon code.
 
 
Q