Skip to content

Instantly share code, notes, and snippets.

@profh
Last active November 5, 2023 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save profh/e1d53ad2079f4e9fe4799679de8ca9c1 to your computer and use it in GitHub Desktop.
Save profh/e1d53ad2079f4e9fe4799679de8ca9c1 to your computer and use it in GitHub Desktop.
Combine Exercise Solution
// One solution to the class exercise
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/search/repositories?q=language:swift&sort=stars&order=desc")!
let publisher = URLSession.shared
.dataTaskPublisher(for: url)
.retry(3)
// --- Bringing back our old friends ---
struct Repositories: Codable {
let items: [Repository]
enum CodingKeys: String, CodingKey {
case items
}
}
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"
}
}
// --- Constructing a reactive chain of operators ---
let repoPublisher = publisher
.map(\.data)
.decode(
type: Repositories.self,
decoder: JSONDecoder()
)
.receive(on: DispatchQueue.main)
// --- Updating our UI based on our reactive chain ---
// Some UI 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:
print("ErrorMsg: \(error.localizedDescription)")
case .finished:
break
}
},
receiveValue: { repos in
// Rendering each repository's name and url:
_ = repos.items.map { repo in
print("Name: \(repo.name)")
print("URL: \(repo.htmlURL)")
print("-----")
}
}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment