HomeiOS Developmentios - In Swift I am making an attempt to know the...

ios – In Swift I am making an attempt to know the circulate of logic when utilizing Sendable, nonisolated, and Actors


My understanding is the TripsFeedViewModel runs on the MainActor as a result of observable so this class is principally remoted to an actor, the MainActor. So in a way it does stop knowledge races. Then once we tripService.getTrips() the principle thread will cross it to a a background thread to attend within the queue/lock of the TripService actor. As soon as the thread is allowed within the TripService actor it initializes the NetworkRequestService which is then certain to that actor and so wouldn’t it’s features. So once we name sendRequest which is a technique of the NetworkRequestService it will run on the TripService actor and the thread would wait till there’s a response again, holding how the lock. Nonetheless, is we mark is as nonisolated it may be handed to a background thread to finish then a thread can decide it up and enter the queue once more. in order that’s why now we have to mark it as nonisolated and the NetworkRequestService as sendable as a result of its secure to ship throughout threads since there are not any mutable states. Then in relation to the PrivateTripResponse it’s technically at all times sendable as a result of its a struct and a replica is created as an alternative of getting references to it. Since PrivateTripResponse conforms to Codable it runs on the MainActor so marking it as nonisolated lets it get decoded on a background actor as properly and its secure as a result of its sendable. So sendbale and nonisolated is working hand and hand letting the complier know is one thing is thread-safe to ship throughout threads with knowledge races. Would this rationalization seize what’s going on on this total circulate?

import Basis

@Observable
class TripsFeedViewModel {
    var journeys: [Trip] = []
    
    personal let tripService: TripServiceProtocol
    
    init(tripService: TripServiceProtocol) {
        self.tripService = tripService
    }
    
    func getTrip() async -> Void {
        do {
            let journeys = strive await tripService.getTrips()
            await MainActor.run {
                self.journeys = journeys.compactMap {
                    Journey(
                        id: $0.id,
                        tripName: $0.tripName,
                        location: $0.location,
                        price range: $0.price range,
                        isFavorite: $0.isFavorite,
                        startDate: $0.startDate,
                        endDate: $0.endDate,
                        imageURLString: $0.imageURL
                    )
                }
            }
        } catch {
            print("There was an error get your journeys: (error.localizedDescription)")
        }
    }
}
import Basis

actor TripService: TripServiceProtocol {
    personal let networkService: NetworkRequestService
    personal let keychainService: KeychainService
    personal var activeTask: Activity?

    init(networkService: NetworkRequestService, keychainService: KeychainService) {
        self.networkService = networkService
        self.keychainService = keychainService
    }
    
    func getTrips() async throws -> [TripPrivateResponse] {
        if let current = activeTask {
            return strive await current.worth
        }
        
        let process = Activity {
            guard let url = URL(string: "native host url") else {
                throw APIError.invalidURL
            }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            
            if let token = keychainService.getToken() {
                request.setValue("Bearer (token)", forHTTPHeaderField: "Authorization")
            }
            
            return strive await networkService.sendRequest(request: request, responseType: [TripPrivateResponse].self)
        }
        
        activeTask = process
        
        defer { activeTask = nil }
        
        return strive await process.worth
    }
}
struct TripPrivateResponse: nonisolated Codable, Sendable {
    let id: Int
    let tripName: String
    let location: String
    let price range: Int
    let isFavorite: Bool
    let startDateString: String
    let endDateString: String
    let imageURLString: String
    
    enum CodingKeys: String, CodingKey {
            case id
            case tripName = "title"
            case location
            case price range
            case isFavorite = "is_favorite"
            case startDateString = "start_date"
            case endDateString = "end_date"
            case imageURLString = "cover_image_url"
        }
}
closing class NetworkRequestService: Sendable {
    // MARK: Sends the request and returns the response from FastAPI
    nonisolated func sendRequest(request: URLRequest, responseType: Output.Kind) async throws -> Output {
        do {
            /// 1. this sends the information to FastAPI then waits for a response
            let (knowledge, response) = strive await URLSession.shared.knowledge(for: request)
            
            print("FASTAPI RESPONSE: (String(knowledge: knowledge, encoding: .utf8) ?? "No Information")")
            
            /// 2. checks the response (convert it to HTTPURLResponse kind) ensuring it has a profitable standing code
            guard let httpResponse = response as? HTTPURLResponse, (200...299).comprises(httpResponse.statusCode) else {
                throw APIError.invalidResponse
            }
            
            /// 3. decode it to the DTO (UserPrivateResponse)
            return strive JSONDecoder().decode(responseType, from: knowledge)
        } catch let error as URLError {
            throw APIError.networkError(error)
        } catch let error as DecodingError {
            throw APIError.decoding(error)
        }
    }
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments