【问题标题】:How to use Combine collect method after a map如何在地图后使用组合收集方法
【发布时间】:2020-05-17 11:41:03
【问题描述】:

我想使用Combine 的collect 方法将对象数组拆分为多个数组的数组,这些数组对应于集合视图中的行(例如:[Item, Item, Item, Item, Item] 将变为[[Item, Item, Item], [Item, Item]] 等等)

我的数据来自我链接的两个发布者,以将我的数据合并为我的视图使用的单一类型。

这是我的代码:

APIClient().send(APIEndpoints.searchMovies(for: text)).flatMap { response -> AnyPublisher<APIResponseList<TVShow>, Error> in
            movies = response.results.map { SearchItemViewModel(movie: $0)}
            return APIClient().send(APIEndpoints.searchTVShows(for: text))
        }
        .map { response -> [SearchItemViewModel] in
            tvShows = response.results.map { SearchItemViewModel(tvShow: $0)}
            let concatItems = tvShows + movies
            return concatItems.sorted { $0.popularity > $1.popularity }
        }
        .collect(3)
        .sink(receiveCompletion: { (completion) in
            switch completion {
            case .failure:
                self.state = .error
                self.items = []
            case .finished:
                break
            }
        }, receiveValue: { (response) in
            self.state = .data
            self.items = response
        })
            .store(in: &disposables)

我目前的问题是在我的 sink receiveValue 闭包中,response 参数不等于预期结果,它只是将我的所有项目分组到一个数组中,如下所示:[Item, Item, Item, Item, Item] -> @987654329 @ collect 方法似乎没有按预期工作,知道如何解决这个问题吗?

【问题讨论】:

  • collect() 不能按预期工作的原因是上一节只返回一项,即数组[Item, Item, Item, Item, Item]。您是否总是有 5 个项目要转换为 [[Item, Item, Item], [Item, Item]]?还是有什么动态要求?
  • 嗯,我明白了,不,它并不总是大约 5 个项目,我的数组(电影和电视节目)都是从 API(TMDb API)获取的,因此每个数组都包含 X 元素。不知道如何才能获得预期的结果。
  • 这绝对是可行的,只要你能清楚地定义如何将 X 项拆分为两个数组的规则。第一个是3,第二个是X-3吗?还是第一个轮(X/2),第二轮X轮(X/2)?
  • 不,我只想将我的项目按 3 分组,如果项目数不是 3 的倍数,则最后一个数组(组)将包含 2 或 1 个项目
  • 那么,您希望拥有多个数组,每个数组包含 3 个或更少的元素?

标签: swift combine


【解决方案1】:

它只是将我所有的项目分组到一个这样的数组中:[Item, Item, Item, Item, Item]

通过flatMap 传递它并生成它的序列发布者。现在 Item 对象将一次到达一个,collect(3) 将按您的预期工作。

例子:

var storage = Set<AnyCancellable>()
let head = Just([1,2,3,4,5]) // this is the same as your `.map`
head
    .flatMap { $0.publisher }
    .collect(3)
    .sink{print($0)} // prove that it works: [1, 2, 3], then [4, 5]
    .store(in: &storage)

【讨论】:

    【解决方案2】:

    创建这个扩展:

    extension Array {
        func split(numItems:Int) -> [[Element]] {
            var i = 0
            var ret = [[Element]]()
            var current = [Element]()
            while i < self.count {
                current.append(self[i])
                i += 1
                if i % numItems == 0 {
                    ret.append(current)
                    current = []
                }
            }
            if current.count > 0 {
                ret.append(current)
            }
            return ret
        }
    }
    

    现在,你应该可以这样做了:

    APIClient().send(APIEndpoints.searchMovies(for: text)).flatMap { response -> AnyPublisher<APIResponseList<TVShow>, Error> in
                movies = response.results.map { SearchItemViewModel(movie: $0)}
                return APIClient().send(APIEndpoints.searchTVShows(for: text))
            }
            .map { response -> [SearchItemViewModel] in
                tvShows = response.results.map { SearchItemViewModel(tvShow: $0)}
                let concatItems = tvShows + movies
                var sorted =  concatItems.sorted { $0.popularity > $1.popularity }
                return sorted.split(numItems:3)
            }
            .sink(receiveCompletion: { (completion) in
                switch completion {
                case .failure:
                    self.state = .error
                    self.items = []
                case .finished:
                    break
                }
            }, receiveValue: { (response) in
                self.state = .data
                self.items = response
            })
                .store(in: &disposables)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 2018-12-02
      • 2017-06-08
      • 1970-01-01
      • 2011-03-04
      相关资源
      最近更新 更多