Swift 合并转换一组发布者
Swift Combine transform an array of publishers
我正在学习 Combine 位 我似乎并没有全神贯注于一些琐碎的操作。我正在构建一个基于执行一些 HealthKit 操作的 Combine。我主要有两个操作:
func workouts(_ limit: Int) -> AnyPublisher<[HKWorkout], Error>
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)
现在我想查询第二个函数。它以锻炼作为参数,并 returns 有关 HKWorkout
的更多信息。如何使用返回的 [HKWorkout]
查询第二个函数,但不知道如何处理。
- 是否应该在第一种方法的接收器部分以嵌套方式进行查询?
- 有没有办法为
[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({
[=13=].publisher.eraseToAnyPublisher()
}).flatMap({
[=13=].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)
我正在学习 Combine 位 我似乎并没有全神贯注于一些琐碎的操作。我正在构建一个基于执行一些 HealthKit 操作的 Combine。我主要有两个操作:
func workouts(_ limit: Int) -> AnyPublisher<[HKWorkout], Error>
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)
现在我想查询第二个函数。它以锻炼作为参数,并 returns 有关 HKWorkout
的更多信息。如何使用返回的 [HKWorkout]
查询第二个函数,但不知道如何处理。
- 是否应该在第一种方法的接收器部分以嵌套方式进行查询?
- 有没有办法为
[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({
[=13=].publisher.eraseToAnyPublisher()
}).flatMap({
[=13=].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)