如何在地图后使用 Combine collect 方法
How to use Combine collect method after a map
我想使用 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: [=10=])}
return APIClient().send(APIEndpoints.searchTVShows(for: text))
}
.map { response -> [SearchItemViewModel] in
tvShows = response.results.map { SearchItemViewModel(tvShow: [=10=])}
let concatItems = tvShows + movies
return concatItems.sorted { [=10=].popularity > .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]
-> [[Item, Item, Item, Item, Item]]
collect
方法似乎没有按预期工作,知道如何解决这个问题吗?
创建此扩展:
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: [=11=])}
return APIClient().send(APIEndpoints.searchTVShows(for: text))
}
.map { response -> [SearchItemViewModel] in
tvShows = response.results.map { SearchItemViewModel(tvShow: [=11=])}
let concatItems = tvShows + movies
var sorted = concatItems.sorted { [=11=].popularity > .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)
it just group all my items into an array like this : [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 { [=10=].publisher }
.collect(3)
.sink{print([=10=])} // prove that it works: [1, 2, 3], then [4, 5]
.store(in: &storage)
我想使用 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: [=10=])}
return APIClient().send(APIEndpoints.searchTVShows(for: text))
}
.map { response -> [SearchItemViewModel] in
tvShows = response.results.map { SearchItemViewModel(tvShow: [=10=])}
let concatItems = tvShows + movies
return concatItems.sorted { [=10=].popularity > .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]
-> [[Item, Item, Item, Item, Item]]
collect
方法似乎没有按预期工作,知道如何解决这个问题吗?
创建此扩展:
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: [=11=])}
return APIClient().send(APIEndpoints.searchTVShows(for: text))
}
.map { response -> [SearchItemViewModel] in
tvShows = response.results.map { SearchItemViewModel(tvShow: [=11=])}
let concatItems = tvShows + movies
var sorted = concatItems.sorted { [=11=].popularity > .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)
it just group all my items into an array like this :
[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 { [=10=].publisher }
.collect(3)
.sink{print([=10=])} // prove that it works: [1, 2, 3], then [4, 5]
.store(in: &storage)