我有一个计时器视图,我想重复使用它,我想通过这样运行的绑定变量来启动计时器:
不幸的是,我今天早上太累了,无法找到解决方法。 :(
也许我的解决方案不好,还有更简单的方法!?
struct TimerView: View {
@State var hours : Int = 0
@State var minutes : Int = 0
@State var seconds : Int = 0
@State var hundred : Int = 0
@Binding var running : Bool
let timer = Timer.publish (every: 0.01, on: .main, in: .common)
@State var cancellable : Cancellable?
func start() {
self.cancellable = timer.connect()
}
func stop() {
cancellable!.cancel()
}
答案 0 :(得分:3)
您可以执行以下操作,创建此扩展名
extension Binding {
func didSet(execute: @escaping (Value) ->Void) -> Binding {
return Binding(
get: {
return self.wrappedValue
},
set: {
let snapshot = self.wrappedValue
self.wrappedValue = $0
execute(snapshot)
}
)
}
}
还有父视图,而不是TimerView
,您可以拥有类似的东西
//[...]
TimerView(running: $running.didSet{ value in /* your code or function here*/ })
//[...]
检查我的答案here
根据评论,我了解到您想从TimerView外部启动/停止计时器。
我找到了几种方法
第一个将TimerView声明为父视图中的变量
struct ContentView: View {
@State var running: Bool = false
@State var timerView: TimerView? = nil
init() {
timerView = TimerView(running: $running)
}
// rest...
}
但是根据您的初始化情况,这可能会很痛苦,因此我创建了一个小的扩展程序,使您可以像这样引用视图
extension View {
func `referenced`<T>(by reference: Binding<T>) -> (Self?){
DispatchQueue.main.async { reference.wrappedValue = self as! T }
return self
}
}
此扩展程序的用法非常简单
struct ContentView: View {
@State var running: Bool = false
@State var timerView: TimerView? = nil
var body: some View {
TimerView(running: $running).referenced(by: $timerView)
}
}
然后您可以使用按钮Button(action: self.timerView.start()) { Text("Start Timer") }
如果针对您的TimerView测试了此代码,但stop()
代码似乎有问题。我在cancellable!.cancel()
行中添加了注释,并添加了print
,一切都按预期进行。
Here's我在Xcode Playground中使用的测试代码
我希望这是您要寻找的答案。