首页 > 解决方案 > 访问组合运算符链中使用的值

问题描述

我想知道是否可以访问组合运算符链中的值,这些值在链中被进一步使用。

例如,如果您有一个字符串数组,并且您使用每个字符串下载一个资源,是否可以访问字符串本身?

也许一个伪代码示例将有助于更好地理解:

let strings = ["a", "b", "c"]

strings.publisher
    .compactMap{ str in
        URL(string: "https://someresource/\(str)")
    }
    .flatMap { url  in
        URLSession.shared.dataTaskPublisher(for: url)
    }
    .map { $0.data}
    .map { data in
        // here I would need the "str" string from above
    }

非常感谢帮助

谢谢,格雷戈尔

标签: swiftcombine

解决方案


杰克写和删除的答案是正确的。我不知道他为什么删除它;也许他觉得他不能用示例代码来支持它。但答案是完全正确的。如果您str稍后在管道中需要初始值,可以在每一步中继续传递它。您通常通过在每个阶段传递一个值的元组来做到这一点,以便字符串使其在链中足够远以便被检索。这是组合编程中非常常见的策略。

举个简单的例子,看看本文中心部分的组合代码:

https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/

正如我在文章中所说:

您会观察到,与 GCD 不同,GCD 中的局部变量只是神奇地“通过”到较低范围级别的嵌套完成处理程序,组合管道中的每个步骤都必须明确传递后续步骤可能需要的所有信息. 这可能会导致一些相当笨拙的值在管道中运行,通常以元组的形式,正如我在此处说明的那样。

但我不认为这是一个问题。相反,在我看来,明确传递管道的内容似乎是一种清晰的收获。

为了进一步说明,这是对您的伪代码的重写;这是真实的代码,您可以运行它并尝试一下:

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)
    }
}

这不是表达管道的唯一方法,但它确实有效,它应该给你一个起点。


推荐阅读