Как последовательно отображать массив текстов с помощью SwiftUI?

#swiftui

#swiftui

Вопрос:

У меня есть список строк, которые я хочу последовательно показывать пользователю. Например:

 var array = ["Hey there!", "What's your name?"]
  

Чего я конкретно хочу, так это показать первую строку в течение нескольких секунд, а когда это время пройдет, показать следующую.

Вот что я сделал до сих пор:

 struct ContentView: View {
    @State private var array = ["Hey there!", "What's your name?"]

    var body: some View {
        VStack {
            TimedTextView(text: array.first, numberOfVisibilitySeconds: 3, onFinishedShowing: {
                self.array.removeFirst()
            })
        }
    }
}
  

И вот TimedTextView :

 struct TimedTextView: View {
    @State private var shouldMakeTextVisible = true

    var text: String!
    var numberOfVisibilitySeconds: Double!
    var onFinishedShowing: (() -> Void)!

    var body: some View {
        VStack {
            if shouldMakeTextVisible {
                Text(text)
                    .font(.largeTitle)
                    .transition(.asymmetric(insertion: .opacity, removal: .opacity))
                    .animation(.easeIn)
                    .onAppear(perform: {
                        DispatchQueue.main.asyncAfter(deadline: .now()   numberOfVisibilitySeconds) {
                            withAnimation {
                                self.shouldMakeTextVisible.toggle()
                            }
                        
                            self.onFinishedShowing()
                        }
                })
            }
        }
    }
}
  

Как вы можете видеть, я использую замыкание, чтобы сообщить ContentView , что Text отображение завершено, и получить следующий. Но на самом деле происходит то, что я вижу только первую строку… Есть идеи, что я делаю не так?

Ответ №1:

Вот возможное решение:

 struct TimedTextContainer: View {
    @State private var currentIndex = 0
    @State private var isVisible = true

    let textArray: [String]

    var visibilityFor: TimeInterval
    var delay: TimeInterval

    var body: some View {
        if currentIndex < textArray.count, isVisible {
            Text(textArray[currentIndex])
                .font(.largeTitle)
                .id(currentIndex)
                .transition(.asymmetric(insertion: .opacity, removal: .opacity))
                .animation(.easeIn)
                .onAppear {
                    DispatchQueue.main.asyncAfter(deadline: .now()   visibilityFor) {
                        withAnimation {
                            isVisible = false
                        }
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now()   visibilityFor   delay) {
                        withAnimation {
                            currentIndex  = 1
                            isVisible = true
                        }
                    }
                }
        }
    }
}
  
 struct ContentView: View {
    let textArray = ["Hey there!", "What's your name?"]

    var body: some View {
        TimedTextContainer(textArray: textArray, visibilityFor: 3, delay: 1)
    }
}
  

Комментарии:

1. Просто идеально! Спасибо!