如何对不同的 ServiceProtocol 使用多线程操作 - Swift

How to use multithreaded operations for different ServiceProtocol - Swift

我正在尝试在我的应用程序中使用 OperationQueue 的多线程操作。

确实,我想在启动期间从所有不同的网络服务中获取我的所有数据,以便在我到达主页时一切就绪。

但我不知道如何正确地做到这一点。

下面是一些可视化代码:

class LauncherService {

    weak var serviceForecast: ForecastServiceProtocol?
    weak var serviceRadar: RadarServiceProtocol?
    weak var serviceWarning: WarningServiceProtocol?
    weak var serviceRain: RainServiceProtocol?

    init(serviceForecast: ForecastServiceProtocol = ForecastService.shared,
         serviceRadar: RadarServiceProtocol = RadarService.shared,
         serviceWarning: WarningServiceProtocol = WarningService.shared,
         serviceRain: RainServiceProtocol = RainService.shared) {

        self.serviceForecast = serviceForecast
        self.serviceRadar = serviceRadar
        self.serviceWarning = serviceWarning
        self.serviceRain = serviceRain
    }

    func requestAllServices(forCity city: City, completion: ((Result<Bool, ErrorResult>) -> Void)? = nil) {

        if let lat = city.lat,
            let lon = city.lon {
            self.fetchForecast(lat: lat, lon: lon)
            self.fetchRain(lat: lat, lon: lon)
        }

        self.fetchWarning()
        self.fetchRadar()
    }
}

我想等到所有服务都完成工作后再"notify" evertyhing is ready to go.

的主页

这里是来自所有不同 ServiceProtocol 的方法的实现:

我只给你看一个,但是所有服务的实现是完全一样的:

func fetchForecast(lat: String, lon: String, completion: ((Result<Bool, ErrorResult>) -> Void)? = nil) {

        guard let service = serviceForecast else {
            completion?(Result.failure(ErrorResult.custom(string: "Missing service")))
            return
        }

        service.fetchForecast(lat: lat, lon: lon) { result in

            DispatchQueue.main.async {
                switch result {
                case .success(let forecast) :
                    // DO something with this Forecast Model Object
                    // Add it in an array on return in completion
                    // But I would like to regroup all the different Model Objects from all my services. 
                    completion?(Result.success(true))
                    break

                case .failure(let error) :
                    print("Something went wrong - \(error)")
                    completion?(Result.failure(error))
                    break
                }
            }
        }
    }

我已阅读 OperationQueue 是我的用例在此处采用的解决方案。

我应该实现这样的东西吗?

let queue = OperationQueue()

for service in services {
    queue.addOperation {
        self.fetch()
    }
}

queue.waitUntilAllOperationsAreFinished()

您可以使用 DispatchGroup

    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    fetchForecast {
        dispatchGroup.leave()
    }

    dispatchGroup.enter()
    fetchRain {
        dispatchGroup.leave()
    }

    dispatchGroup.notify(queue: .main) {
        print("All done")
    }

最后一个块将在两个请求都完成加载后执行。