访问 combine-operator-chain 中使用的值
Access used values in a combine-operator-chain
我想知道是否可以访问组合运算符链中的值,这些值将在链中进一步使用。
例如,如果您有一个字符串数组,并且您为每个字符串下载了一个资源,是否可以访问该字符串本身?
也许一个伪代码示例将有助于更好地理解:
let strings = ["a", "b", "c"]
strings.publisher
.compactMap{ str in
URL(string: "https://someresource/\(str)")
}
.flatMap { url in
URLSession.shared.dataTaskPublisher(for: url)
}
.map { [=10=].data}
.map { data in
// here I would need the "str" string from above
}
非常感谢帮助
谢谢,格雷戈尔
杰克写下并删除的答案是正确的。我不知道他为什么删除它;也许他觉得他不能用示例代码来支持它。但答案是完全正确的。如果稍后在管道中需要初始 str
值,则由 you 将其传递到每个步骤。您通常通过在每个阶段传递值的 元组 来做到这一点,以便字符串使其在链中足够远以便被检索。这是 Combine 编程中非常的常用策略。
举个简单的例子,看一下本文中间部分的Combine代码:
https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/
正如我在文章中所说:
You’ll observe that, as opposed to GCD where local variables just magically “fall through” to nested completion handlers at a lower level of scope, every step in a Combine pipeline must explicitly pass down all information that may be needed by a later step. This can result in some rather ungainly values working their way down the pipeline, often in the form of a tuple, as I’ve illustrated here.
But I don’t regard that as a problem. On the contrary, being explicit about what’s passing down the pipeline seems to me to be a gain in clarity.
为了进一步说明,这里重写了您的伪代码;这是真实的代码,你可以 运行 试试看:
class ViewController: UIViewController {
var storage = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
let strings = ["a", "b", "c"]
let pipeline = strings.publisher
.map { str -> (String, URL) in
let url = URL(string: "https://www.apeth.com/pep/manny.jpg")!
return (str, url)
}
.flatMap { (str, url) -> AnyPublisher<(String, (data: Data, response: URLResponse)), URLError> in
let sess = URLSession.shared.dataTaskPublisher(for: url)
.eraseToAnyPublisher()
let just = Just(str).setFailureType(to: URLError.self)
.eraseToAnyPublisher()
let zip = just.zip(sess).eraseToAnyPublisher()
return zip
}
.map { (str, result) -> (String, Data) in
(str, result.data)
}
.sink { comp in print(comp) } receiveValue: { (str, data) in print (str, data) }
pipeline.store(in: &storage)
}
}
这不是表达管道的唯一方法,但它确实有效,而且应该为您提供一个起点。
我想知道是否可以访问组合运算符链中的值,这些值将在链中进一步使用。
例如,如果您有一个字符串数组,并且您为每个字符串下载了一个资源,是否可以访问该字符串本身?
也许一个伪代码示例将有助于更好地理解:
let strings = ["a", "b", "c"]
strings.publisher
.compactMap{ str in
URL(string: "https://someresource/\(str)")
}
.flatMap { url in
URLSession.shared.dataTaskPublisher(for: url)
}
.map { [=10=].data}
.map { data in
// here I would need the "str" string from above
}
非常感谢帮助
谢谢,格雷戈尔
杰克写下并删除的答案是正确的。我不知道他为什么删除它;也许他觉得他不能用示例代码来支持它。但答案是完全正确的。如果稍后在管道中需要初始 str
值,则由 you 将其传递到每个步骤。您通常通过在每个阶段传递值的 元组 来做到这一点,以便字符串使其在链中足够远以便被检索。这是 Combine 编程中非常的常用策略。
举个简单的例子,看一下本文中间部分的Combine代码:
https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/
正如我在文章中所说:
You’ll observe that, as opposed to GCD where local variables just magically “fall through” to nested completion handlers at a lower level of scope, every step in a Combine pipeline must explicitly pass down all information that may be needed by a later step. This can result in some rather ungainly values working their way down the pipeline, often in the form of a tuple, as I’ve illustrated here.
But I don’t regard that as a problem. On the contrary, being explicit about what’s passing down the pipeline seems to me to be a gain in clarity.
为了进一步说明,这里重写了您的伪代码;这是真实的代码,你可以 运行 试试看:
class ViewController: UIViewController {
var storage = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
let strings = ["a", "b", "c"]
let pipeline = strings.publisher
.map { str -> (String, URL) in
let url = URL(string: "https://www.apeth.com/pep/manny.jpg")!
return (str, url)
}
.flatMap { (str, url) -> AnyPublisher<(String, (data: Data, response: URLResponse)), URLError> in
let sess = URLSession.shared.dataTaskPublisher(for: url)
.eraseToAnyPublisher()
let just = Just(str).setFailureType(to: URLError.self)
.eraseToAnyPublisher()
let zip = just.zip(sess).eraseToAnyPublisher()
return zip
}
.map { (str, result) -> (String, Data) in
(str, result.data)
}
.sink { comp in print(comp) } receiveValue: { (str, data) in print (str, data) }
pipeline.store(in: &storage)
}
}
这不是表达管道的唯一方法,但它确实有效,而且应该为您提供一个起点。