Selecting Multiple Items and then Sorting

I'm trying to learn Swift and SwiftUI, so I tried to write what I thought would be a simple app, but I’ve quickly run into a problem. I want to be able to select multiple languages and then be able to sort those languages.

I found sample code on the web for both tasks, and I thought I understood how they worked, however they use different data structures and I can’t figure out how to reconcile them. In the code below, preferredLanguages is used to select multiple languages, and sortedLangs is used for sorting. Individually those tasks work fine, but I can’t figure out how to share the results of the multiple selection with the sorting view.

Ideally I’d prefer to have just one class or struct, one var, and one view, but if I can’t do that I need to pass the preferredLanguages data to the sortedLangs var.

Suggestions? Is there some sample code somewhere that does this?

enum LanguageCodes: Int, CaseIterable, Identifiable {
case eng = 0
case ell
case deu
//etc.
    var id: LanguageCodes {
        self
    }
    var literal: String {
        switch self {
case .eng: return "eng"
case .ell: return "ell"
case .deu: return "deu"
        }
    }
}

class PreferredLanguages: ObservableObject {
    @Published var languages = [LanguageCodes]()
}

struct IdentifiableLanguageItem: Identifiable  {
    let id = UUID()
    let langCode: LanguageCodes
}

@ObservedObject var preferredLanguages = PreferredLanguages()

@State private var sortedLangs: [IdentifiableLanguageItem]

Replies

What you show is not enough to understand what you've done. So some general advice.

You want to select items in a view and then have another view use them ? Correct ?

If so, @Binding is a good solution.

  • declare a @Binding var languages in the SortingView (that may be an array of LanguageCodes)
  • in the selectionView, you declare a State var selections of the same type than languages
  • when selection done, you call SearchBar(languages: $selections)

Thanks for the reply. I wasn't sure how much code to show. Yes, I want to select multiple items and then have another view to sort them. And by sorting I mean I want the user to be able to drag them into the order desired. I should have made that clear.

I'll look into your suggestions.

So the first part is to do with Binding.

To move is extremely simple:

  • modifier onMove on ForEach
  • a move func
  • as described here https://www.hackingwithswift.com/quick-start/swiftui/how-to-let-users-move-rows-in-a-list
struct ContentView: View {
    @State private var users = ["Paul", "Taylor", "Adele"]

    var body: some View {
        NavigationView {
            List {
                ForEach(users, id: \.self) { user in
                    Text(user)
                }
                .onMove(perform: move)
            }
            .toolbar {
                EditButton()
            }
        }
    }

    func move(from source: IndexSet, to destination: Int) {
        users.move(fromOffsets: source, toOffset: destination)
    }
}

However, in simulator, moving may be a bit whimsical. Better click, pause, move.

  • I took a closer look at your sample code and incorporated an idea from it into mine. And it finally compiled with no errors! Doesn't quite work the way I want it to yet, but I think I'm on the right track now. Thanks again.

Add a Comment

Thanks again. I see I've made a mess of trying to explain my problem. I have code that can do the sort and it looks pretty much like yours. And I have code that selects multiple items, but it's pretty long, which is why I didn't include it.

The problem is the multi-select view uses an array of language codes and the sort/arrange uses an array that's identifiable so it has the UUID in it as well. I don't know how to change my code to use the same var in each view, nor do I know how to take the array of selections and use it to populate the identifiable array. Every way I try, I get cryptic errors.

Maybe instead of referencing my code, I should just ask how can I let the user select multiple items and then arrange those items in the desired order?