swift - Swift Combine 转换一组发布者
问题描述
我正在通过组合位我似乎并没有围绕一些琐碎的操作。我正在构建一个基于执行一些 HealthKit 操作的组合。主要我有两个操作:
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)
现在我想查询第二个函数。它将锻炼作为参数并返回有关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({
$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)
推荐阅读
- ios - React Native iOS 发布构建链接问题
- flutter - 我的颤振应用程序可以在运行时配置为使用用户自定义 FCM 项目设置吗?
- c# - Expression.Call 导致“静态方法需要空实例,非静态方法需要非空实例”
- java - 如何使用java从给定列中的excel中获取唯一记录
- google-cloud-run - 有没有办法监控来自 Google Cloud Run 控制台的网络流量/出口?
- regex - 正则表达式检查字符串中是否存在两个不同的字符组
- javascript - navigator.getUserMedia 不是 startVideo (script.js:3) at script.js:9 的函数
- c# - 如何等到列表填充到 Plugin.Ble 中?
- python - 将格式(YYYY-MM-DD)中的日期拆分为数据框中的 3 个新列,分别为 Year、Month 和 Date
- vbscript - 服务器对象错误“ASP 0177:800401f3”