无法为SwiftUI计时器设置变量间隔

时间:2019-12-29 23:20:54

标签: xcode timer swiftui

我正在尝试在SwiftUI视图中自动显示一系列图像。我可以创建一个固定的 具有预定“每个”值的计时器,并在.onReceive中触发视图更新 关闭,但我无法构造一个带有间隔属性的计时器 用户可以使用滑块对其进行调整。以下代码适用于固定 计时器。订阅会正确触发,但我似乎找不到对应的订阅 .onReceive以订阅更新图像。我也尝试创建自己的 TimerPublisher,但是我有同样的问题-如果不指定,则无法初始化 固定值。

我的观点:

struct ImageStream2: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: DermPhoto.getAllDermPhotos()) var dermPhotos: FetchedResults<DermPhoto>
    @State private var activeImageIndex = 0
    @State private var animateSpeed: Double = 1.0
    @State private var startTimer = false

    let timer = Timer.publish(every: 1.0, on: .main, in: .default).autoconnect()
    @State private var mst: MyTimerSubscription!

    var body: some View {
        GeometryReader { geo in
            VStack {
                Text("Time Sequence")
                    .foregroundColor(.blue)
                    .font(.system(size: 25))
                Image(uiImage: UIImage(data: self.dermPhotos[self.activeImageIndex].myImage!)!)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: geo.size.width - 20, height: geo.size.width - 20, alignment: .center)
                    .cornerRadius(20)
                    .shadow(radius: 10, x: 10, y: 10)

                    .onReceive(self.timer) { t in
                        print("in fixed timer")
                        if self.startTimer {
                            self.activeImageIndex = (self.activeImageIndex + 1) % self.dermPhotos.count
                        }
                    }
                Group {
                    HStack {
                        Text("0.5").foregroundColor(.blue)
                        Slider(value: self.$animateSpeed, in: 0.5...5.0, step: 0.5)
                        Text("5.0").foregroundColor(.blue)
                    }
                    .padding()
                    Text("Replay at: " + "\(self.animateSpeed) " + (self.animateSpeed == 1.0 ? "second" : "seconds") + " per frame")
                        .foregroundColor(.blue)
                    HStack {
                        Button(action: {
                            self.startTimer.toggle()
                            if self.startTimer {
                                self.mst = MyTimerSubscription(interval: 5.0)
                            } else {
                                self.mst.subscription.cancel()
                            }
                        }) {
                            ZStack {
                                RoundedRectangle(cornerRadius: 20)
                                    .fill(Color.yellow)
                                    .frame(width: 200, height: 40)
                                Text(self.startTimer ? "Stop" : "Start").font(.headline)
                            }
                        }
                    }
                    .padding()
                }//group
            }//top VStack
        }.onDisappear{ self.startTimer = false }
    }
}

订阅文件:

class MyTimerSubscription {
    let subscription: AnyCancellable
    let interval: Double
    init(interval: Double) {
        subscription =
            Timer.publish(every:interval, on:.main, in:.default)
                .autoconnect()
                .sink { _ in
                    print("in MyTimerSubscription print")
        }
        self.interval = interval
    }

    deinit {
        subscription.cancel()
    }
}

任何指导将不胜感激。 Xcode 11.3(11C29)

1 个答案:

答案 0 :(得分:0)

这似乎有点糊涂,但是我做了一个解决方案。更改计时器初始化 成为国家财产。

@State var timer = Timer.publish(every: 1.0, on: .main, in: .default).autoconnect()

然后在我用来启动图像流的按钮操作中:

self.timer = Timer.publish(every: self.animateSpeed, on: .main, in: .default).autoconnect()

然后在按钮操作中停止流:

self.timer.upstream.connect().cancel()