Created
October 31, 2023 11:23
-
-
Save profh/d6543b9bf35914555b1c1e821f4c9e7d to your computer and use it in GitHub Desktop.
Revisions
-
profh created this gist
Oct 31, 2023 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,101 @@ // h/t to @JohnSundell (https://www.swiftbysundell.com/) import UIKit import Combine import PlaygroundSupport // This playground will execute indefinetly in order to give our // async operations enough time to execute. PlaygroundPage.current.needsIndefiniteExecution = true // --- Creating a publisher for performing a network request --- // Note: set a retry automatically (3x) if request fails let url = URL(string: "https://api.github.com/repos/67443-Mobile-Apps/RepoBrowser2022")! // for class exercise, change the url to: // let url = URL(string: "https://api.github.com/search/repositories?q=language:swift&sort=stars&order=desc")! let publisher = URLSession.shared .dataTaskPublisher(for: url) .retry(3) // --- Bringing back our old friend, Repository --- struct Repository: Codable, Identifiable { let id: Int let name: String let htmlURL: String let itemDescription: String? enum CodingKeys: String, CodingKey { case id case name case htmlURL = "html_url" case itemDescription = "description" } } // --- Subscribing to our publisher using sink() --- let cancellableSubscriber = publisher.sink( receiveCompletion: { completion in switch completion { case .failure(let error): print(error) case .finished: print("Success") } }, receiveValue: { value in let decoder = JSONDecoder() do { // Since each value passed into our closure will be a tuple // containing the downloaded data, as well as the network // response itself, we're accessing the 'data' property here: let repo = try decoder.decode(Repository.self, from: value.data) print(repo) } catch { print(error) } } ) // --- Constructing a reactive chain of operators --- let repoPublisher = publisher .map(\.data) .decode( type: Repository.self, decoder: JSONDecoder() ) .receive(on: DispatchQueue.main) // --- Updating our UI based on our reactive chain --- // Two labels that we want to render our data using: let nameLabel = UILabel() let urlLabel = UILabel() let errorLabel = UILabel() let cancellableRepoSubscriber = repoPublisher.sink( receiveCompletion: { completion in switch completion { case .failure(let error): // Rendering a description of the error that was encountered: errorLabel.text = error.localizedDescription print("ErrorMsg: \(error.localizedDescription)") case .finished: break } }, receiveValue: { repo in // Rendering the downloaded repository's name and url: nameLabel.text = repo.name urlLabel.text = repo.htmlURL print("Name: \(repo.name)") print("URL: \(repo.htmlURL)") } )