iosswiftsearchpaginationpaginator

Pagination doesn't set back to first page after search box is cleared


I'm using Swift for iOS app development and encountering a problem with pagination function.

The idea is quite straightforward. As the query is entered, the search function should return all possible results, and list them 10 rows per page using paginator if the results are more than 10. The user may browse to each result page by clicking paginator. However, it should always goes back/set to the first result page (current paginator should equal to 0) when the search box is cleared or emptied by the user and get ready for next input.

The problem currently occurring is that after browsing the result page of previous query with paginator, it never set back to first page when the search box is cleared for new query. In result, the new query search results started showing from current page number of previous browsed page number, which ended up the results from page 1 are overlooked and the user has to use paginator one by one to go back to see the results in first page.

Current code is as follows:

import SwiftUI

class DictionaryViewModel: ObservableObject {
@Published var filteredWordPairs: [WordPair] = []
@Published var searchText = "" {
    didSet {
        filterWordPairs()
    }
}

private var allWordPairs: [WordPair] = DataLoader.loadCSVFile()
private var currentPage = 0
private let pageSize = 10

func wordPairsForPage(_ pageIndex: Int, pageSize: Int) -> ArraySlice<WordPair> {
    let startIndex = pageIndex * pageSize
    let endIndex = min(startIndex + pageSize, filteredWordPairs.count)
    
    if startIndex >= endIndex {
        return []
    }
    
    return filteredWordPairs[startIndex..<endIndex]
}

var canGoToNextPage: Bool {
    return (currentPage + 1) * pageSize < filteredWordPairs.count
}

func gotoPreviousPage() {
    currentPage = max(currentPage - 1, 0)
}

func gotoNextPage() {
    if canGoToNextPage {
        currentPage += 1
    }
}

private func filterWordPairs() {
    if searchText.isEmpty {
        filteredWordPairs = []
    } else {
        let lowercaseSearchText = searchText.lowercased()
        filteredWordPairs = allWordPairs.filter { wordPair in
            let lowercasedWord1 = wordPair.Word1.lowercased()
            let lowercasedWord2 = wordPair.Word2.lowercased()
            
            return lowercasedWord1 .contains(lowercaseSearchText) ||
            lowercasedWord2.contains(lowercaseSearchText) ||
            lowercasedWord1.range(of: lowercaseSearchText) != nil ||
            lowercasedWord2.range(of: lowercaseSearchText) != nil
        }
    }
    currentPage = 0 // Reset currentPage when search text changes
    
}

}

Solution

  • When the search text changes, you correctly reset the currentPage to 0, but you're not updating the currentPage when the user navigates through the pages using the paginator. I think you need to reset currentPage to 0 when searchText.isEmpty. Here's updated code

        @Published private var currentPage = 0
    
        private func filterWordPairs() {
            if searchText.isEmpty {
                filteredWordPairs = []
                currentPage = 0 // Reset currentPage when search text is cleared
            } else {
                let lowercaseSearchText = searchText.lowercased()
                filteredWordPairs = allWordPairs.filter { wordPair in
                    let lowercasedWord1 = wordPair.Word1.lowercased()
                    let lowercasedWord2 = wordPair.Word2.lowercased()
    
                    return lowercasedWord1.contains(lowercaseSearchText) ||
                        lowercasedWord2.contains(lowercaseSearchText) ||
                        lowercasedWord1.range(of: lowercaseSearchText) != nil ||
                        lowercasedWord2.range(of: lowercaseSearchText) != nil
                }
                currentPage = 0 // Reset currentPage when search text changes
            }
        }