Повторяющийся таймер прерывает плавное перетаскивание UIImage - PullRequest
0 голосов
/ 24 октября 2018

Когда я начинаю перетаскивать изображение, оно запускает таймер, но каждую секунду (когда таймер повторяется) перетаскивание прерывается, и изображение появляется в начальной позиции в течение миллисекунды.Вот видео .Если я удаляю таймер, то перетаскивание работает должным образом.

Я создал пользовательский класс для перетаскиваемого изображения (DragItem), в котором при касании изображения публикуется уведомление, которое запускает таймер на ViewController.

Я предполагаю, что этот сбой может быть связан с RunLoop.main.add (timer, forMode: RunLoop.Mode.common) , однако я не могу понять, как это исправить,Есть идеи?

Вот наиболее близкие темы, которые мне удалось найти: Таймер не работает при перетаскивании и Приостановка таймера при прокрутке

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)

}

}

...