Search code examples
arraysswiftsortingswiftuilocalizedstringkey

How to sort a array with localized String in SwiftUI


Hi my problem is that i want to sort an array of objects by the object's title property. When i change the title's type from String to LocalizedStringKey i get an error. Is there a way to sort the correct translated string behind the localizedStringKey.

struct Item: Codable,Comparable, Hashable, Identifiable {
    static func < (lhs: Item, rhs: Item) -> Bool {
        return lhs.title < rhs.title
    }
    
    var id: Int
    
    let image: String
    let color: String
    
//    title should be LocalizedStringKey
    let title: String

    }
......

    @State private var sortedDown = false
    var filteredItems: [Item] {
        var sortedItems: [Item]
        let filteredItems = modelData.items.filter { item in
            (!showFavoritesOnly || item.isFavorite)
        }
        if sortedDown {
            sortedItems = filteredItems.sorted(by: { (item1, item2) -> Bool in
                return item1.title > item2.title
            })
        } else {
            sortedItems = filteredItems.sorted(by: { (item1, item2) -> Bool in
                return item1.title < item2.title
            })
        }
        return sortedItems
    }
    
    
    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $showFavoritesOnly, label: {
                    Text("showFavorites")
                })
                ForEach(filteredItems) { (item) in
.....

``

Solution

  • Don't forget to provide a minimal reproducible example when you ask questions. You will get better and more focused answers. Below is one way you can do it.

    class LocalizeTitleViewModel: ObservableObject {
        @Published var items: [SampleItem] = [SampleItem(title: "orange", isFavorite: true), SampleItem(title: "pink", isFavorite: false), SampleItem(title: "red", isFavorite: true)]
        @Published var sortedDown = false
        @Published var showFavoritesOnly = false
        var filteredItems: [SampleItem] {
            var sortedItems: [SampleItem]
            let filteredItems = items.filter { item in
                (!showFavoritesOnly || item.isFavorite)
            }
            if sortedDown {
                sortedItems = filteredItems.sorted(by: { (item1, item2) -> Bool in
                    return item1.localizedTitle > item2.localizedTitle
                })
            } else {
                sortedItems = filteredItems.sorted(by: { (item1, item2) -> Bool in
                    return item1.localizedTitle < item2.localizedTitle
                })
            }
            return sortedItems
        }
    }
    struct LocalizeTitle: View {
        @StateObject var modelData: LocalizeTitleViewModel = LocalizeTitleViewModel()
        var body: some View {
            NavigationView {
                List {
                    Toggle(isOn: $modelData.showFavoritesOnly, label: {
                        Text("showFavorites")
                    })
                    ForEach(modelData.filteredItems) { (item) in
                        
                        Text(item.localizedTitle)
                    }
                }
            }
        }
    }
    struct SampleItem: Identifiable {
        
        var id: UUID = UUID()
        let title: String
        var isFavorite: Bool
        
        var localizedTitle: String{
            get{
                //You need a Localizable.strings file in your project that contains all your `title`
                return NSLocalizedString(self.title, comment: "Sample Item title")
            }
        }
    }
    struct LocalizeTitle_Previews: PreviewProvider {
        static var previews: some View {
            LocalizeTitle()
        }
    }