当我开始拖动图像时,它会触发一个计时器,但是每秒(当计时器重复执行时)拖动都会中断,并且图像会在开始位置出现几毫秒。这是video。如果我删除计时器,则拖动可以正常工作。
我为可拖动图像(DragItem)创建了自定义类,其中当图像被触摸时会在其中发布通知,从而在ViewController上触发计时器。
我认为此故障可能与 RunLoop.main.add(timer,forMode:RunLoop.Mode.common)有关,但是,我无法弄清楚如何解决它。有什么想法吗?
以下是我能够找到的最接近的主题:Timer not working when dragging和timer pauses when scrolling
DragItem:UIImageView类
var dragItemOrigin: CGPoint!
var dropTaget: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "touchedDragItem"), object: nil)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let location = touch.location(in: self.superview)
self.center = location
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.3, animations: {
if let touch = touches.first, let target = self.dropTaget {
let position = touch.location(in: self.superview)
if target.frame.contains(position) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onTargetDropped"), object: nil)
}
}
})
}
ViewController
var counter = 4.0
var timer: Timer!
var isTimerRunning = false
var MAX_PENALTIES = 3
var penalties: Int = 0
let dragItemInCode: DragItem = {
let imageView = DragItem(frame: CGRect.zero)
imageView.image = UIImage(named: "Oval1.png")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.isUserInteractionEnabled = true
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(dragItemInCode)
counter = 4
view.bringSubviewToFront(dragItemInCode)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.dragItemTouched(_:)), name:NSNotification.Name(rawValue: "touchedDragItem"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.dragItemDroppedOnDropItem(_:)), name:NSNotification.Name(rawValue: "onTargetDropped"), object: nil)
setupLayout()
}
private func setupLayout() {
dragItemInCode.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
dragItemInCode.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
dragItemInCode.widthAnchor.constraint(equalToConstant: 35).isActive = true
dragItemInCode.heightAnchor.constraint(equalToConstant: 35).isActive = true
//dragItemInCode.layoutIfNeeded()
}
@objc func dragItemTouched(_ sender: NSNotification) {
print("item touched")
startTimer()
}
func startTimer() {
timer = Timer(timeInterval: 4, target: self, selector: #selector(ViewController.changeGameState), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
}
@objc func dragItemDroppedOnDropItem(_ sender: NSNotification) {
print("item dropped")
}
func timerLabelUpdates() {
timerLbl.text = String(format: "%.1f", counter)
if counter <= 0 {
penalties += 1
} else {
self.counter -= 0.1
}
}
@objc func changeGameState() {
timerLbl.text = String(format: "%.1f", counter)
if counter > 0 {
self.counter -= 1
} else {
gameOver()
}
func gameOver() {
timer.invalidate()
dropItemLbl.playDeathAnimation()
UIView.animate(withDuration: 1, delay: 0.5, options: .curveEaseInOut, animations: {
Vibration.error.vibrate()
self.dragItemInCode.alpha = 0
self.explosion()
}, completion: nil)
}
func explosion() {
let emitter = ExplodeView.get(with: #imageLiteral(resourceName: "particle"))
emitter.emitterPosition = CGPoint(x: dragItemInCode.frame.width / 2, y: dragItemInCode.frame.height/2)
emitter.emitterSize = dragItemInCode.bounds.size
dragItemInCode.layer.addSublayer(emitter)
}
}