Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SwiftUI实例@State变量_Swift_State_Swiftui_Reset - Fatal编程技术网

SwiftUI实例@State变量

SwiftUI实例@State变量,swift,state,swiftui,reset,Swift,State,Swiftui,Reset,我对SwiftUI还是个新手。我有一个“计数器”视图,它每秒钟计数一次。当颜色改变时,我想“重置”计数器: struct MyCounter : View { let color: Color @State private var count = 0 init(color:Color) { self.color = color _count = State(initialValue: 0) } var body: some View { Text(

我对SwiftUI还是个新手。我有一个“计数器”视图,它每秒钟计数一次。当颜色改变时,我想“重置”计数器:

struct MyCounter : View {
  let color: Color
  @State private var count = 0

  init(color:Color) {
    self.color = color
    _count = State(initialValue: 0) 
  }
  var body: some View {
    Text("\(count)").foregroundColor(color)
    .onAppear(){
        Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.count = self.count + 1 }
    }
  }
}
以下是我使用计数器的主要视图:

struct ContentView: View {
  @State var black = true
  var body: some View {
    VStack {
        MyCounter(color: black ? Color.black : Color.yellow)
        Button(action:{self.black.toggle()}) { Text("Toggle") }
    }
  }
}

当我单击“切换”按钮时,我看到调用了MyCounter构造函数,但@State计数器仍然存在,并且从不重置。所以我的问题是如何重置这个@State值?请注意,我不希望使用counter作为@Binding并在父视图中管理它,而是希望MyCounter是一个自包含的小部件。(这是一个简化的示例。我正在创建的真正的小部件是一个执行精灵动画的精灵动画师,当我交换图像时,我希望动画师从第0帧开始)。谢谢

您需要一个绑定变量:

struct MyCounter : View {
      let color: Color
      @Binding var count: Int
      var body: some View {
      Text("\(count)").foregroundColor(color)
            .onAppear(){
                Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.count = self.count + 1 }
            }
       }
}

struct ContentView: View {
    @State var black = true
    @State var count : Int  = 0
    var body: some View {
         VStack {
              MyCounter(color: black ? Color.black : Color.yellow , count: $count)
               Button(action:{self.black.toggle()
                    self.count = 0
                }) { Text("Toggle") }
         }
     }
}
如果您不喜欢绑定,也可以只添加一个状态值
innerColor

struct MyCounter : View {
    let color: Color
    @State private var count: Int = 0
    @State private var innerColor: Color?

    init(color: Color) {
        self.color = color

    }

    var body: some View {

        return Text("\(self.count)")
            .onAppear(){
                Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.count = self.count + 1 }
            }.foregroundColor(color).onReceive(Just(color), perform: { color in
                if self.innerColor !=  self.color {
                self.count = 0
                self.innerColor = color}
            })
    }
}

您需要一个绑定变量:

struct MyCounter : View {
      let color: Color
      @Binding var count: Int
      var body: some View {
      Text("\(count)").foregroundColor(color)
            .onAppear(){
                Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.count = self.count + 1 }
            }
       }
}

struct ContentView: View {
    @State var black = true
    @State var count : Int  = 0
    var body: some View {
         VStack {
              MyCounter(color: black ? Color.black : Color.yellow , count: $count)
               Button(action:{self.black.toggle()
                    self.count = 0
                }) { Text("Toggle") }
         }
     }
}
如果您不喜欢绑定,也可以只添加一个状态值
innerColor

struct MyCounter : View {
    let color: Color
    @State private var count: Int = 0
    @State private var innerColor: Color?

    init(color: Color) {
        self.color = color

    }

    var body: some View {

        return Text("\(self.count)")
            .onAppear(){
                Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.count = self.count + 1 }
            }.foregroundColor(color).onReceive(Just(color), perform: { color in
                if self.innerColor !=  self.color {
                self.count = 0
                self.innerColor = color}
            })
    }
}

有两种方法可以解决这个问题。一种是使用绑定,如E.Coms所解释的,这是解决问题的最简单方法

或者,您可以尝试使用
observateObject
作为计时器的视图模型。这是更灵活的解决方案。计时器可以传递,如果您愿意,也可以作为环境对象注入

class TimerModel:ObservableObject{
//@Published属性包装器确保自动发出objectWillChange信号。
@已发布变量计数:Int=0
init(){}
func start(){
scheduledTimer(withTimeInterval:1,repeats:true){in self.count=self.count+1}
}
函数重置(){
计数=0
}
}
然后,您的计时器视图将变为

struct MyCounter:视图{
让颜色:颜色
@ObservedObject变量计时器:TimerModel
初始化(颜色:颜色,计时器:TimerModel){
self.color=颜色
self.timer=计时器
}
var body:一些观点{
文本(“\(timer.count)”).foregroundColor(颜色)
.onAppear(){
self.timer.start()
}
}
}
您的内容视图变为

struct ContentView:View{
@状态变量black=true
@ObservedObject var timer=TimerModel()
var body:一些观点{
VStack{
MyCounter(颜色:黑色?颜色。黑色:颜色。黄色,计时器:self.timer)
按钮(操作:{
self.black.toggle()
self.timer.reset()
}) { 
文本(“切换”)
}
}
}
}
使用可观察对象的优点是,您可以更好地跟踪计时器。您可以向模型中添加一个
stop()
方法,该方法会使计时器无效,您可以在视图的
onDisappear
块中调用它


对于这种方法,您必须注意的一点是,当您以独立方式使用计时器时,您可以使用MyCounter(颜色:…,timer:TimerModel())在视图生成器闭包中创建它,每次重新渲染视图时,都会替换计时器模型,因此,您必须确保以某种方式保留模型。

有两种方法可以解决此问题。一种是使用绑定,如E.Coms所解释的,这是解决问题的最简单方法

或者,您可以尝试使用
observateObject
作为计时器的视图模型。这是更灵活的解决方案。计时器可以传递,如果您愿意,也可以作为环境对象注入

class TimerModel:ObservableObject{
//@Published属性包装器确保自动发出objectWillChange信号。
@已发布变量计数:Int=0
init(){}
func start(){
scheduledTimer(withTimeInterval:1,repeats:true){in self.count=self.count+1}
}
函数重置(){
计数=0
}
}
然后,您的计时器视图将变为

struct MyCounter:视图{
让颜色:颜色
@ObservedObject变量计时器:TimerModel
初始化(颜色:颜色,计时器:TimerModel){
self.color=颜色
self.timer=计时器
}
var body:一些观点{
文本(“\(timer.count)”).foregroundColor(颜色)
.onAppear(){
self.timer.start()
}
}
}
您的内容视图变为

struct ContentView:View{
@状态变量black=true
@ObservedObject var timer=TimerModel()
var body:一些观点{
VStack{
MyCounter(颜色:黑色?颜色。黑色:颜色。黄色,计时器:self.timer)
按钮(操作:{
self.black.toggle()
self.timer.reset()
}) { 
文本(“切换”)
}
}
}
}
使用可观察对象的优点是,您可以更好地跟踪计时器。您可以向模型中添加一个
stop()
方法,该方法会使计时器无效,您可以在视图的
onDisappear
块中调用它


对于这种方法,您必须注意的一点是,当您以独立方式使用计时器时,您可以使用MyCounter(颜色:…,timer:TimerModel())在视图生成器闭包中创建它,每次重新渲染视图时,都会替换计时器模型,因此,你必须确保以某种方式保留模型。

谢谢,但这是我不想要的一个解决方案(在帖子中提到)。如果MyCounter是“独立的”,那就太好了。谢谢。我想第二种选择是正确的。遗憾的是,没有简单的方法来重新初始化状态值。谢谢,但这是我不想要的一个解决方案(在文章中提到)。如果MyCounter是“独立的”,那就太好了。谢谢。我想第二种选择是正确的。遗憾的是,没有简单的方法来重新初始化状态值。你能解释为什么会出现这种情况吗?W