简体   繁体   中英

How to create views in SwiftUI using collect

I am trying to figure out a way to insert multiple arrays of views in a VStack in SwiftUI using collect() operator.

struct ChatsTab: View {
    var subscriptions = Set<AnyCancellable>()
    var body: some View {
        VStack {
            ["A", "B", "C", "D", "E"].publisher.collect(2).sink(receiveCompletion: { _ in
                // Do nothing on completion
            }) { (stringArray) in
                HStack {
                    Text(stringArray[0])
                    Text(stringArray[1])
                }
            }
        .store(in: &subscriptions)
        }
    }
}

But I'm getting this below error:

Cannot convert value of type '()' to closure result type '_'

I want to do this with collect only so I can add my text views in pair. I know I have other options but I want to get it done with collect only.

You just have to rearrange things. The real issue is not the collect , the issue is that you're trying to execute arbitrary code inside the VStack . The VStack is a function builder and between it's curly braces goes a list of views and possibly some basic if logic only. Not arbitrary code, like the kind you include in a regular function. So if you take the publisher code out of the VStack it will compile. Where you put it is up to you, you can have it in init() , called from another function, or int didAppear view modifier (just not inside the VStack directly).

A second issue is that the collect will publish another array (one of length 2). You will essentially end up with an array of String arrays (or you can just consume them as they are published and not keep them around, depending on what you are trying to do). You can also use the simpler version of sink since the Error of the publisher here is Never . Anyway here is something incorporating the above changes:


import SwiftUI
import Combine

var subscriptions = Set<AnyCancellable>()

struct ContentView: View {

  @State var stringArrays: [[String]] = []

    var body: some View {
      ForEach(stringArrays, id: \.self) { stringArray in
        HStack {
          Text(stringArray.count > 0 ? stringArray[0] : "")
          Text(stringArray.count > 1 ? stringArray[1] : "")
        }
      }.onAppear() {
        ["A", "B", "C", "D", "E"].publisher
          .collect(2)
          .sink(receiveValue: { (stringArray) in
            self.stringArrays.append(stringArray)
          }).store(in: &subscriptions)
      }
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM