Swiftui — Как использовать таймер.запланированное время применяется для просмотра UIView каждые n секунд

#swift #swiftui #uiview

Вопрос:

Я новичок в SwiftUI, чтобы сделать вид похожим на то, что я сделал в UIKit. пробовал почти несколько часов, но успеха не добился.

вот мой код в UIKit, который хорошо работает в моем проекте.

   var positionY = self.view.frame.height
     let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { (timer) in
           // do stuff 3 seconds later
         positionY = positionY - 50
        let bubble = UIView(frame: CGRect(x: self.view.frame.width/2, y:  positionY, width: 50, height: 50))
        bubble.backgroundColor = UIColor.red
        self.view.addSubview(bubble)
       
      }
    
    RunLoop.current.add(timer, forMode: .common)
 

сейчас я работаю над SwifUI. Мне нужно такое же поведение в моем проекте SwiftUI, потому что я много чего сделал с этим кодом.

Ответ №1:

Настройте его в соответствии с вашими требованиями:

 struct ContentView: View {
    
    @State private var positionYOffset: CGFloat = 0
    private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
    var body: some View {
        
        GeometryReader { geometry in
            
            Rectangle()
                .fill(Color.red)
                .frame(width: 50, height: 50)
                .position(x: geometry.size.width/2, y: geometry.size.height - positionYOffset)
        }.onReceive(timer) { _ in
           positionYOffset  = 50
        }
    }
}
 

Ответ №2:

SwiftUI работает немного иначе, чем UIKit. Есть много способов сделать это.

 import SwiftUI
//Model acts like the UIViewController (vaguely)
class MultipleBubbleViewModel: ObservableObject{
    //Set the initial value to zero
    @Published var position: CGFloat = CGFloat.zero
    //Keep track of the bubbles (sub views)
    @Published var bubbles: [BubbleViewModel] = []
    private var timer: Timer?
    
    //Uncomment next line to change colors and see how color is observed
    //let bubbleColors: [Color] = [ .orange, .green, .gray ,.blue, .yellow]
    
    func addBubbles(frameSize: CGSize){
        //Start timer
        timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { (timer) in
            // do stuff 3 seconds later
            //adjust position
            self.position -= 50
            //Create bubble
            let bubble = BubbleViewModel(height: 50, width: 50, x: frameSize.width/2, y: self.position, color: .red)
            //Add to array
            self.bubbles.append(bubble)
            
            //This is a little extra
            
            //Uncomment next line to change colors and see how color is observed
            //bubbles.randomElement()!.color = bubbleColors.randomElement()!
            
            if Double(self.bubbles.count * 50) >= Double(frameSize.height - 50) {
                //Stop when the bubbles will get cut off by screen
                timer.invalidate()
            }
        }
    }
}
//This view acts like the storyboard/object (vaguely)
struct MultipleBubbleView: View {
    @StateObject var viewModel: MultipleBubbleViewModel = MultipleBubbleViewModel()
    var body: some View {
        //Gives you the size of the available frame
        GeometryReader{ geo in
            ZStack{
                //Show bubble views for each bubble
                ForEach(viewModel.bubbles){bubble in
                    BubbleView(bubble: bubble)
                }
            }.onAppear(){
                //Set the initial position from frame size
                viewModel.position = geo.size.height
                viewModel.addBubbles(frameSize: geo.size)
            }
        }
    }
    
    
}
//This view acts like the storyboard/object (vaguely)
struct BubbleView: View {
    //If you want to change the bubble's y you need to observe it
    @ObservedObject var bubble: BubbleViewModel
    var body: some View {
        Circle()
            .foregroundColor(bubble.color)
            .frame(width: bubble.width, height: bubble.height)
            .position(x: bubble.x, y: bubble.y)
    }
}
//Model acts like the UIViewController (vaguely)
class BubbleViewModel: Identifiable, ObservableObject{
    let id: UUID = UUID()
    @Published var x: CGFloat
    @Published var y: CGFloat
    @Published var color: Color
    @Published var width: CGFloat
    @Published var height: CGFloat
    init(height: CGFloat, width: CGFloat, x: CGFloat, y: CGFloat, color: Color){
        self.height = height
        self.width = width
        self.color = color
        self.x = x
        self.y = y
    }
    
    
}
struct MultipleBubbleView_Previews: PreviewProvider {
    static var previews: some View {
        MultipleBubbleView()
    }
}
 

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

1. ваш код работает очень хорошо, но, к сожалению, у меня есть два метода с передачей UIView для анимации пузырьков. пожалуйста, посмотрите мой обновленный раздел. спасибо вам за вашу помощь

2. Посмотрите на ваш другой вопрос. После того, как я это сделал, я понял, что пару дней назад ты задал еще один вопрос. Новый код-это гораздо больше, чем первоначальный вопрос. Если бы я ответил на ваш первоначальный вопрос. Пожалуйста, примите ответ и проголосуйте, если хотите.

3. конечно, я не буду делать никаких проблем вообще

4. Не могли бы вы помочь мне преобразовать этот вопрос в SwiftUI, пожалуйста.

5. Почему ты переводишь? Если у вас есть это в UIKit, почему бы не завернуть то, что у вас есть, в UIViewRepresentable или UIViewControllerRepresentable