This is an example of how to apply NetworkManager in an app.
- Swift 6.0
- iOS 18.4
- Xcode 16.3
- Swift concurrency: async/await
- New
Observation
framework (@Observable
) - MVVM architecture
extension NetworkConfiguration {
static var baseURL: URL? {
URL(string: "https://api.example.com")
}
static var apiVersion: String? { "/v1" }
}
struct UserRequest: Requestable {
typealias Response = UserModel
var urlPath: String = "/users"
var httpMethod: HTTPMethod = .get
}
@Observable
final class UserViewModel {
var users: [UserModel]?
func fetchUsers() async {
do {
let userRequest = UserRequest()
users = try await userRequest.request()
} catch {
// Handle error
}
}
}
struct LoginRequest: Requestable {
typealias Response = LoginModel
var urlPath: String = "/login"
var httpMethod: HTTPMethod = .post
var requestBody: Codable? {
LoginRequestBody(username: username, password: password)
}
let username: String
let password: String
}
fileprivate struct LoginRequestBody: Codable {
let username: String
let password: String
}
@Observable
final class LoginViewModel {
var token: String?
@ObservationIgnored private var loginModel: LoginModel?
func login(username: String, password: String) async {
do {
let loginRequest = LoginRequest(username: username, password: password)
loginModel = try await loginRequest.request()
if let token = loginModel?.token {
self.token = token
}
} catch {
// Handle error
}
}
}
struct UserRequest: Requestable {
typealias Response = UserModel
var urlPath: String = "/users"
var httpMethod: HTTPMethod = .get
var headers: [String : String]? {
["Content-Type": "application/json"]
}
}
struct UserRequest: Requestable {
typealias Response = UserModel
var urlPath: String = "/users"
var httpMethod: HTTPMethod = .get
var queryParameters: [String : String]? {
["sort": "asc"]
}
}
Output URL: https://api.example.com/users?sort=asc