OneBusAway / onebusaway-ios

OneBusAway for iOS, written in Swift.
Other
81 stars 33 forks source link

Replace RESTAPIService Operations with Swift Concurrency implementation #622

Closed ualch9 closed 1 year ago

ualch9 commented 1 year ago

The goal is to make the codebase more approachable to first-time contributors by adopting Swift Structured Concurrency. The result from this refactor will be more readable business logic and a net-decrease in LOCs.

OBAKit API change

Before

// Keep track of operation
var operation: DecodableOperation<RESTAPIResponse<StopArrivals>>?

deinit {
    operation?.cancel()
}

func loadData() {
    let op = apiService.getArrivalsAndDeparturesForStop(
        id: stopID, 
        minutesBefore: minutesBefore, 
        minutesAfter: minutesAfter
    )

    op.complete { [weak self] result in
        guard let self else { return }
        switch (result) {
        case .failure(let error):
            // Show error in UI
        case .success(let response):
            // Show arrivals in UI
    }
    self.operation = op
}

After

func loadData() async {
    do {
        let stopArrivals: RESTAPIResponse<StopArrivals> = try await apiService
            .getArrivalsAndDeparturesForStop(
                id: stopID, 
                minutesBefore: minutesBefore, 
                minutesAfter: minutesAfter
            )
        // Handle success
    } catch {
        // Handle failure
    }
}

This is part-one of Concurrency adoption. Lots of bandaids and deprecation warnings are present, but I want to keep PRs reasonably sized.