view - SwiftUI:如何使用计时器在不同位置创建多个视图?
问题描述
在老式 swift 中准备以下任务非常容易:每三秒一个新视图(子视图)出现在一个新位置。这是一个代码:
import UIKit
class ViewController: UIViewController {
var someView = UIView()
var posX : CGFloat = 10
var posY : CGFloat = 10
var timer:Timer!
var loopCount = 1
override func viewDidLoad() {
super.viewDidLoad()
startTimer()
view.backgroundColor = .purple
}
func setView() {
someView = UIView(frame: CGRect(x: posX, y: posY, width: 10, height: 10))
someView.backgroundColor = UIColor.orange
view.addSubview(someView)
}
func startTimer() {
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(loop), userInfo: nil, repeats: true)
}
}
@objc func loop(){
if (loopCount % 3 == 0) {
posX += 15
posY += 15
setView()
}
loopCount += 1
}
}
SwiftUI 让很多事情变得更容易,但恐怕不是这一件事。至少直到现在我还没有找到一个简单的方法来解决它。有人知道吗?
这是显示结果的屏幕(几秒钟后):
解决方案
这是可能的方法(使用 Xcode 11.2 / iOS 13.2 测试)。SwiftUI 是响应式概念,因此它不是添加视图本身,而是在视图模型中添加一个新位置,并且 SwiftUI 视图响应视图模型的这种变化刷新自身,在新添加的位置添加新视图(在本例中为矩形)。
演示(开始录制的时刻不准确,但会定期添加矩形):
代码:(另见一些内联评论)
// needed to use as ID in ForEach
extension CGPoint: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.x)
hasher.combine(self.y)
}
}
// View model holding and generating new positions
class DemoViewModel: ObservableObject {
@Published var positions = [CGPoint]() // all points for view
private var loopCount = 0
func loop() {
if (loopCount % 3 == 0) {
if let last = positions.last { // generate new point
positions.append(CGPoint(x: last.x + 15, y: last.y + 15))
} else {
positions.append(CGPoint(x: 10, y: 10))
}
}
loopCount += 1
}
}
struct DemoAddingView: View {
@ObservedObject var vm = DemoViewModel()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
ZStack {
ForEach(vm.positions, id: \.self) { position in
Rectangle().fill(Color.orange) // just generate a rect view for all points
.frame(width: 10, height: 10)
.position(position) // location of rect in global coordinates
}
.onReceive(timer) { _ in
self.vm.loop() // add next point
}
}
}
}
推荐阅读
- javascript - 3D Globe.gl 的性能问题
- java - 使用 Spring Boot Actuator 和 git-commit-id-maven-plugin 格式化 Git/构建时间信息
- javascript - NodeJS中的Jinja SQL等价物?
- python-3.x - CSV 到 XML 交替值
- haskell - Rust 向量中的 Haskell 样式的链表添加
- php - Laravel - PHP - 通过作曲家安装 HTML 包失败
- javascript - 如何使用 Swift 和 JavaScript 在 WKWebView 中滚动文本
- typescript - 如何计算打字稿中对象的动态键类型
- xcode - xcode 12中的lldb printf
- android - Android MVVM ROOM 单一事实来源问题