Swift Combine转换出版商数组



我正在通过组合位获得我的方式,我似乎没有在一些琐碎的操作中缠绕我的头。我正在构建一个基于HealthKit操作的Combine。主要有两个操作:

  1. func workouts(_ limit: Int) -> AnyPublisher<[HKWorkout], Error>
  2. func workoutDetails(_ workout: HKWorkout) -> AnyPublisher<WorkoutDetails, Error>

首先,我将使用第一个查询一些锻炼,这很容易。

HKHealthStore().workouts(HKObjectQueryNoLimit)
.sink(receiveCompletion: { subject in
switch subject {

case .finished:
break
case .failure(let error):
dump(error)
}
}, receiveValue: { workouts in
dump(workouts)
// What now? 
}).store(in: &bag)  

现在我想查询第二个函数。它将训练作为参数,并返回有关HKWorkout的更多信息。我如何用返回的[HKWorkout]查询第二个函数,但不知道如何接近它。

  • 我应该在第一个方法的sink部分以嵌套的方式进行查询吗?
  • 是否有一种方法可以为[HKWorkout]中的每个锻炼嵌套操作并为每个锻炼调用workoutDetails(_ workout: HKWorkout),以便我得到[WorkoutDetails]的结果?

到目前为止,我所尝试的都不成功。

HKHealthStore().workouts(HKObjectQueryNoLimit)
.map({ workouts -> AnyPublisher<[WorkoutDetails], Never> in

return workouts.publisher.flatMap({ workout in
return Just(workout as! [WorkoutDetails]).eraseToAnyPublisher()
.eraseToAnyPublisher()
})
.eraseToAnyPublisher()

}).sink(receiveCompletion: { subs in
switch subs {

}
}, receiveValue: { val in
/// Cannot convert value of type 'AnyPublisher<[WorkoutDetails], Never>' to expected argument type 'Void'
/// I am not able to get [WorkoutDetails] here as I'd like
dump(val)
})
.store(in: &bag)

编辑:我终于使用的解决方案。有两个选项,我终于设法使它工作并理解它。

一个是@New Dev最终在sink中接收组合数组的答案,另一个是在sink上接收单个元素以保存在数组中。

HKHealthStore().workouts(HKObjectQueryNoLimit)
.flatMap({
$0.publisher.eraseToAnyPublisher()
}).flatMap({
$0.workoutWithDetails
}).sink(receiveCompletion: { comp in
switch comp {
case .finished:
break
case .failure(let er):
dump(er)
}
}, receiveValue: { details in
/// Add the individual `WorkoutDetails` elements to an array 
results.append(details)
}).store(in: &SGHealthManager.bag)

一般的方法是将数组flatMap转换为单个值的Sequence发布者,然后对每个值执行任何异步操作(另一个flatMap),然后collect结果:

HKHealthStore()
.workouts(HKObjectQueryNoLimit)
.flatMap { workouts in workouts.publisher }
.flatMap { workout in
workoutDetails(workout)
}
.collect()
.sink(
receiveCompletion: { ... },
receiveValue: { arrayOfWorkoutDetails in
// arrayOfWorkoutDetails is of type [WorkoutDetails]
})
.store(in: &bag)

最新更新