Skip to content

Instantly share code, notes, and snippets.

@codewithsanthoshofficial
Created February 10, 2026 18:34
Show Gist options
  • Select an option

  • Save codewithsanthoshofficial/f8e446da2e628c0aa6c799d29f71629f to your computer and use it in GitHub Desktop.

Select an option

Save codewithsanthoshofficial/f8e446da2e628c0aa6c799d29f71629f to your computer and use it in GitHub Desktop.
SwiftUI_apiCall_Combine
import Foundation
import Combine
enum HttpMethod:String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
}
enum NetworkError:Error {
case invlaidURL
case serverError(Int)
case decodingError
case unknown
}
class APIService {
static let shared = APIService()
private init(){ }
func request<T:Codable>(endpoint:String, method:HttpMethod = .get, headers: [String: String]? = nil, parameters: [String: Any]? = nil) -> AnyPublisher<T, Error> {
guard let url = URL(string: endpoint) else {
return Fail(error: NetworkError.invlaidURL).eraseToAnyPublisher()
}
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
headers?.forEach {
request.addValue($0.value, forHTTPHeaderField: $0.key)
}
if let parameters {
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
}
let urlsession = URLSession.shared.dataTaskPublisher(for: request)
// 1. Check for HTTP status codes
.tryMap { output in
guard let response = output.response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
throw NetworkError.serverError((output.response as? HTTPURLResponse)?.statusCode ?? 500)
}
return output.data
}
// 2. Decode the JSON
.decode(type: T.self, decoder: JSONDecoder())
// 3. Move back to the Main Thread for UI updates
.receive(on: DispatchQueue.main)
// 4. Erase type to make it reusable
.eraseToAnyPublisher()
return urlsession
}
}
=========
import Foundation
enum APIEndPoint {
static let baseURL = "https://newsapi.org/v2/everything?q=tesla&from=2026-01-10&sortBy=publishedAt&apiKey="
case news
var url:String {
switch self {
case .news : return "\(APIEndPoint.baseURL)"
}
}
}
import Foundation
import Combine
class NewsViewModel:ObservableObject {
@Published var newList:[Articles] = []
@Published var errorMessage:String?
@Published var showError:Bool = false
// This stores your subscriptions so they don't get cancelled immediately
private var cancellables = Set<AnyCancellable>()
init() {
getNews()
}
func getNews() {
let publisher: AnyPublisher<NewsModelRes, Error> = APIService.shared.request(endpoint: APIEndPoint.news.url)
//Publisher: URLSession starts the data flow.
publisher
.receive(on: DispatchQueue.main)
// Specifying the type we expect (NewsResponse)
.sink { [weak self] completion in
switch completion {
case .finished:
break // Do nothing on success
case .failure(let error):
self?.errorMessage = error.localizedDescription
self?.showError = true
}
} receiveValue: { [weak self] response in
// This only runs if the request succeeds
self?.newList = response.articles ?? []
}
.store(in: &cancellables) // Keep the subscription alive
}
}
//POST
//let response:NewsModelRes = try await APIService.shared.request(endpoint: APIEndPoint.news.url, method: .put, headers: nil, parameters: [:])
===================
import Foundation
struct NewsModelRes:Codable {
let status:String?
let totalResults:Int?
let articles:[Articles]?
enum CodingKeys: String, CodingKey {
case status
case totalResults
case articles
}
}
struct Articles:Codable, Identifiable {
var id : String {url ?? ""}
let author: String?
let title: String?
let description: String?
let url: String?
let urlToImage: String?
enum CodingKeys: String, CodingKey {
case author
case title
case description
case url
case urlToImage
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment