arraysswiftbuttonswiftuiforeach

When I select a button its position changes, why?


Code: I just want tick on selected button view and need that selected button schoolCode but my code i got check mark also and selected button code also but if i select button its position changes.. if i select 3rd button then it comes to 2nd place like that... please fix this error

ScrollView(.horizontal, showsIndicators: false) {
    HStack {
        if let retrievedArray = UserDefaults.standard.stringArray(forKey: "SavedSchoolCodes") {
            let uniqueItems = Array(Set(retrievedArray))

            ForEach(uniqueItems, id: \.self) { item in
                if let school = schoolList.first(where: { $0.schoolCode == item }) {
                    Button {
                        viewModel.schoolCode = school.schoolCode ?? ""
                    } label: {
                        ZStack {
                            let correctedPhotoURL = school.logo?.replacingOccurrences(of: "//SchImg", with: "/SchImg") ?? ""
                            VStack {

                                URLImageView(url: correctedPhotoURL, placeholder: "NoProfilePic", width: 50, height: 50)

                                    .clipShape(Circle())
                                    .padding(.bottom, 4)
                                Text(school.schoolCode ?? "")
                                    .font(.headline)
                                    .foregroundColor(.black)
                            }
                            .frame(width: 100, height: 120)
                            .background(Color.gray.opacity(0.2))
                            .cornerRadius(10)

                            RoundedRectangle(cornerRadius: 10)

                                .stroke(viewModel.schoolCode == school.schoolCode ? Color.green : Color.clear, lineWidth: 2)
                                .frame(width: 100, height: 120)

                            if viewModel.schoolCode == school.schoolCode {

                                Image(systemName: "checkmark.circle.fill")
                                    .resizable()
                                    .frame(width: 20, height: 20)
                                    .foregroundColor(.green)
                                    .offset(x: 35, y: -45)
                            }
                        }
                    }
                    .padding(5)
                } else {
                    Text("\(item),")
                }
            }
        } else {
            Text("No array found in UserDefaults.")
        }
    }
    .padding(.horizontal)
}

o/p: when i select i just want checkmark thats it.. please guide to fix change position.


Solution

  • You are converting the list of school codes to a Set, then you iterate over the set and find the corresponding School for each code.

    A Set is an unordered collection. The ordering of the schools in your view is therefore unpredictable and indeed it seems to change when the view is re-rendered to show the selected school.

    Try sorting the array that you create from the Set:

    let uniqueItems = Array(Set(retrievedArray)).sorted()