GCD的替代方案是在SwiftUI下延迟运行代码

GCD的替代方案是在SwiftUI下延迟运行代码,swift,swiftui,grand-central-dispatch,nsoperationqueue,nsoperation,Swift,Swiftui,Grand Central Dispatch,Nsoperationqueue,Nsoperation,Swift 5,iOS 13 我正在运行这个代码,它可以工作 var body: some View { ... Button(action: { self.animateTLeft() quest = quest + "1" }) { Wedge(startAngle: .init(degrees: 180), endAngle: .init(degrees: 270)) .fill(Color.red) .frame(width: 200,

Swift 5,iOS 13

我正在运行这个代码,它可以工作

var body: some View {
...
Button(action: {
  self.animateTLeft() 
  quest = quest + "1"
}) { Wedge(startAngle: .init(degrees: 180), endAngle: .init(degrees: 270)) 
         .fill(Color.red) 
         .frame(width: 200, height: 200)
         .offset(x: 95, y: 95)
         .scaleEffect(self.tLeft ? 1.1 : 1.0)
}.onReceive(rPublisher) { _ in
  self.animateTLeft() 
}
...
}

private func animateTLeft() {
withAnimation(.linear(duration: 0.25)){
  self.tLeft.toggle()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
  withAnimation(.linear(duration: 0.25)){
    self.tLeft.toggle()
  }
})
}
如果可能的话,我想尝试一些使用GCD的替代方法而不是。所以我试着用了一个定时器,它没有编译。我试着使用perform,它也没有编译。所以我尝试了编译!:)的操作。但可悲的是,这只会起作用一次。除了GCD,别无选择

private func animateTLeft() {

//perform(#selector(animate), with: nil, afterDelay: 0.25)
//Timer.scheduledTimer(timeInterval: 0.15, target: self, selector: #selector(animateRed), userInfo: nil, repeats: false)

let queue = OperationQueue()
let operation1 = BlockOperation(block: {
  withAnimation(.linear(duration: 1)){
    self.tLeft.toggle()
  }
})
let operation2 = BlockOperation(block: {
  withAnimation(.linear(duration: 1)){
    self.tLeft.toggle()
  }
})
operation2.addDependency(operation1)
queue.addOperations([operation1,operation2], waitUntilFinished: true)

}
为什么我要这样做,因为我有四个切片,我想动画,但我想要更少的代码。我有红色、绿色、黄色和蓝色的薄片。我编写了一个通用例程来设置它们的动画,并将颜色作为参数提供。这是我的密码

private func animateSlice(slice: inout Bool) {
withAnimation(.linear(duration: 0.25)){
  slice.toggle()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
  withAnimation(.linear(duration: 0.25)){
    slice.toggle()
  }
})
}
但当inout参数给出红色错误消息“转义闭包捕获'inout'参数'slice'”时,这将无法编译,这是不好的。我可以复制它,而不是在inout参数中。这会编译,但当然不起作用,因为它不会更改愚蠢的值

我也试过了,但无法编译。也许有人能让它工作

private func animateSliceX(slice: String) {
var ptr = UnsafeMutablePointer<Bool>.allocate(capacity: 1)
switch slice {
case "red": ptr = &tLeft
case "green": ptr = &tRight
case "yellow": ptr = &bLeft
default: ptr = &bRight
}
withAnimation(.linear(duration: 0.25)){
  ptr.toggle()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
  withAnimation(.linear(duration: 0.25)){
    ptr.toggle()
  }
})
}
private func animateSliceX(切片:字符串){
var ptr=unsafemeutablepointer.allocate(容量:1)
开关片{
案例“红色”:ptr=&tLeft
案例“绿色”:ptr=&tRight
案例“黄色”:ptr=&bLeft
默认值:ptr=&bRight
}
带动画(.linear(持续时间:0.25)){
ptr.toggle()
}
DispatchQueue.main.asyncAfter(截止日期:.now()+0.25,执行:{
带动画(.linear(持续时间:0.25)){
ptr.toggle()
}
})
}

谢谢…

我认为没有其他方法(至少更容易使用GCD),但您可以使用以下可重用功能

假设该切片是一个状态或一个值类型为Bool的绑定,则可以执行以下操作:

private func animateSlice(slice: Binding<Bool>) {
    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.25) {
        withAnimation(Animation.linear(duration: 0.25)) {
            slice.wrappedValue.toggle()
        }
    }
}

好的,所以我接受了另一个答案,因为我认为这是一个比这个更好的答案,但我认为无论如何我都会发布这个,因为它是相同问题的另一个解决方案

private func animate(slice: String) {
    animateAction(slice: slice)
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
      self.animateAction(slice: slice)
    })
  }

 private func animateAction(slice: String) {
    withAnimation(.linear(duration: 0.25)){
      switch slice {
        case "red": self.tLeft.toggle()
        case "green": self.tRight.toggle()
        case "yellow": self.bLeft.toggle()
    // blue is the only other slice
        default: self.bRight.toggle()
      }
    }
  }

如果我使用GCD,我可能会使用组合方法,例如:

struct ContentView: View {
    var body: some View {
        Button(action: {
            DispatchQueue.main.schedule(after: .init(.now() + 1)) {
                print("bar")
            }
        }) {
            Text("foo")
        }
    }
}
如果您不想使用GCD,您可以使用
计时器

struct ContentView: View {
    var body: some View {
        Button(action: {
            Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
                print("bar")
            }
        }) {
            Text("foo")
        }
    }
}

或者正如用户3441734所说,您也可以在
RunLoop
上使用
schedule

struct ContentView: View {
    var body: some View {
        Button(action: {
            RunLoop.main.schedule(after: .init(Date() + 1)) {
                print("bar")
            }
        }) {
            Text("foo")
        }
    }
}

你可以使用RunLoop,看,我确实提出了另一个版本[可以使用],但它有12行代码,我用了8行代码。这意味着你赢了:)优秀的编码。。将在media.com上的Better programming中发布我的代码。在你的档案档案档案中添加一封电子邮件,这样我可以给你一些信用。
struct ContentView: View {
    var body: some View {
        Button(action: {
            RunLoop.main.schedule(after: .init(Date() + 1)) {
                print("bar")
            }
        }) {
            Text("foo")
        }
    }
}