Created
October 30, 2025 02:16
-
-
Save profh/f3fdaaa9966c46d341c011b8ebdc7c27 to your computer and use it in GitHub Desktop.
Combine_Movie_Search_Filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Combine | |
| import Foundation | |
| // MARK: - Movie Database | |
| let movies = [ | |
| "The Matrix", | |
| "The Godfather", | |
| "The Dark Knight", | |
| "Monty Python and the Holy Grail", | |
| "Forrest Gump", | |
| "Inception", | |
| "The Shawshank Redemption", | |
| "Goodfellas", | |
| "The Empire Strikes Back", | |
| "True Lies", | |
| "Interstellar", | |
| "The Princess Bride", | |
| "Chariots of Fire", | |
| "Gladiator", | |
| "Captain America: Winter Soldier", | |
| "Blade Runner", | |
| "The Lion King", | |
| "Back to the Future", | |
| "Buckaroo Banzai", | |
| "The Avengers" | |
| ] | |
| // MARK: - Search Publisher | |
| let searchPublisher = PassthroughSubject<String, Never>() | |
| // Storage for our subscription | |
| var cancellables = Set<AnyCancellable>() | |
| // MARK: Complete Search Pipeline | |
| searchPublisher | |
| // 1. Debounce: Wait 0.3 seconds after user stops typing | |
| .debounce(for: .milliseconds(300), scheduler: RunLoop.main) | |
| // 2. Filter: Ignore empty search terms | |
| // 3. Map: Filter movies based on search term (case-insensitive) | |
| // 4. Subscribe: Print the results | |
| // if noting, print "no movies found", otherwise print a | |
| // count of the movies found followed by their titles (with a dash) | |
| // 5. Store: Keep the subscription alive | |
| .store(in: &cancellables) | |
| // MARK: - Test Scenarios | |
| // If you did this right, you should get the output given farther below... | |
| print("Starting search filter test...") | |
| print("\n--- First search: 'dark' ---") | |
| searchPublisher.send("dark") | |
| // Wait for debounce, then try another search | |
| DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { | |
| print("\n--- New search: 'go' (2 results) ---") | |
| searchPublisher.send("go") | |
| } | |
| // Try an empty string (should be filtered out) | |
| DispatchQueue.main.asyncAfter(deadline: .now() + 3) { | |
| print("\n--- Testing empty string (should not print any results) ---") | |
| searchPublisher.send("") | |
| } | |
| // Try a search with no matches | |
| DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) { | |
| print("\n--- New search: 'xyz' (no matches) ---") | |
| searchPublisher.send("xyz") | |
| } | |
| // Keep the playground running | |
| import PlaygroundSupport | |
| PlaygroundPage.current.needsIndefiniteExecution = true | |
| // MARK: Expected Output | |
| /* | |
| Starting search filter test... | |
| --- First search: 'dark' --- | |
| Found 1 movie(s): | |
| - The Dark Knight | |
| --- New search: 'go' (2 results) --- | |
| Found 2 movie(s): | |
| - The Godfather | |
| - Goodfellas | |
| --- Testing empty string (should not print any results) --- | |
| --- New search: 'xyz' (no matches) --- | |
| No movies found | |
| */ | |
| /* | |
| KEY LEARNING POINTS SUMMARIZED: | |
| =============================== | |
| - debounce prevents excessive work (important for API calls!) | |
| - filter removes invalid input before expensive operations | |
| - map transforms the stream (here, from String to [String]) | |
| - Case-insensitive search requires lowercasing both sides | |
| - Storing subscription in Set<AnyCancellable> keeps it alive | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment