计时器更新 UILabel.text 导致 TouchesBegan / TouchesEnded 出现故障 - 如何修复?

Timer updating UILabel.text causes TouchesBegan / TouchesEnded to glitch - how to fix?

我已经构建了一个带有多个视图控制器的 Ipad 游戏,在游戏开始时(在 ROOT VC)它会触发一个计时器从 2 小时开始倒计时。 运行 在 XCODE 8.2.1 / Swift 3.

在 ViewController 再往下(第 6 或第 7),我有一个迷你游戏,用户通过 TouchesBegan/TouchesMoved/TouchesEnded。 (UIImageViews 由 Interface Builder 设置)。

屏幕顶部有一个标签(UserInteraction = disabled),通过当前视图控制器时触发的计时器,每 1 秒更新一次到当前剩余时间(在 2 小时倒计时)加载(下面代码中的 showgametimeTimer)。

问题是:这会打乱小游戏(当用户用手指结束拖动时,图像无法"lock" 到达目标位置)并且这 "glitch" 仅在计时器时发生更新标签是 运行。

不过,如果我禁用计时器,一切都会如预期的那样正常工作。

所以在某种程度上,每 1 秒从计时器更新 UILabel.text,调用一些影响 TouchesBegan and/or TouchesEnded 的东西。

UILabel.text在屏幕上方,要移动的对象在下方。我尝试设置布尔逻辑 - 即在 touchesBegan 开始时设置 timer.invalidate,在 TouchesEnded 结束时恢复计时器,但无济于事,问题仍然存在。

修复它的唯一方法是完全禁用此视图控制器的计时器。

我正在添加代码,尽管我认为这对查看问题没有多大帮助 - 我只是想知道是否有人 运行 遇到过相同的问题或知道它的原因/如何解决?初级程序员在这里。

非常感谢

相关代码:

    var showGameTimeTimer = Timer()

    override func viewDidLoad() {
        super.viewDidLoad()

        showGameTimeTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(showTime), userInfo: nil, repeats: true)
        showGameTimeTimer.fire()
    }

    func showTime(){

    TimeLeftLabel.text = gameTimerString // gametimerstring gets updated every second from a timer fired at the Root VC

    }

var initialPosi = CGPoint()
var initialPosiSecond = CGPoint()
var initialPosiThird = CGPoint()
var initialPosiFourth = CGPoint()
var initialPosiFifth = CGPoint()
var initialPosiSixth = CGPoint()
var initialPosiSeventh = CGPoint()
var initialPosiEigth = CGPoint()
var hasTakenFromFirstSlot = 0
var hasTakenFromSecondSlot = 0
var hasTakenFromThirdSlot = 0
var hasTakenFromFourthSlot = 0
var imageSelected = 0
var firstSlotIsTaken = 0
var secondSlotIsTaken = 0
var thirdSlotIsTaken = 0
var fourthSlotIsTaken = 0
var firstSlotHasImageNumber = 0
var secondSlotHasImageNumber = 0
var thirdSlotHasImageNumber = 0
var fourthSlotHasImageNumber = 0

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches) {
            let location = touch.location(in: self.view)



            hasTakenFromFirstSlot = 0
            hasTakenFromSecondSlot = 0
            hasTakenFromThirdSlot = 0
            hasTakenFromFourthSlot = 0

            if FirstImage.frame.contains(location) {
                imageSelected = 1
                FirstImage.center = location
            }
            if secondImage.frame.contains(location) {
                imageSelected = 2
                secondImage.center = location
            }
            if thirdImage.frame.contains(location) {
                imageSelected = 3
                thirdImage.center = location
            }
            if fourthImage.frame.contains(location) {
                imageSelected = 4
                fourthImage.center = location
            }
            if fifthImage.frame.contains(location) {
                imageSelected = 5
                fifthImage.center = location
            }
            if sixthImage.frame.contains(location) {
                imageSelected = 6
                sixthImage.center = location
            }
            if seventhImage.frame.contains(location) {
                imageSelected = 7
                seventhImage.center = location
            }
            if eightImage.frame.contains(location) {
                imageSelected = 8
                eightImage.center = location
            }

            if (FirstImage.frame.contains(location) || secondImage.frame.contains(location)  || thirdImage.frame.contains(location)  || fourthImage.frame.contains(location)   || fifthImage.frame.contains(location)  || sixthImage.frame.contains(location)  || seventhImage.frame.contains(location)  || eightImage.frame.contains(location)  ) && firstCorrectImage.frame.contains(location) && firstSlotIsTaken > 0 && firstSlotHasImageNumber > 0 {
                hasTakenFromFirstSlot = 1
            }

            if (FirstImage.frame.contains(location) || secondImage.frame.contains(location)  || thirdImage.frame.contains(location)  || fourthImage.frame.contains(location)   || fifthImage.frame.contains(location)  || sixthImage.frame.contains(location)  || seventhImage.frame.contains(location)  || eightImage.frame.contains(location)  ) && secondCorrectImage.frame.contains(location) && secondSlotIsTaken > 0 && secondSlotHasImageNumber > 0 {
                hasTakenFromSecondSlot = 1
            }

            if (FirstImage.frame.contains(location) || secondImage.frame.contains(location)  || thirdImage.frame.contains(location)  || fourthImage.frame.contains(location)   || fifthImage.frame.contains(location)  || sixthImage.frame.contains(location)  || seventhImage.frame.contains(location)  || eightImage.frame.contains(location) ) && thirdCorrectImage.frame.contains(location) && thirdSlotHasImageNumber > 0 && thirdSlotIsTaken > 0 {
                hasTakenFromThirdSlot = 1
            }
            if (FirstImage.frame.contains(location) || secondImage.frame.contains(location)  || thirdImage.frame.contains(location)  || fourthImage.frame.contains(location)   || fifthImage.frame.contains(location)  || sixthImage.frame.contains(location)  || seventhImage.frame.contains(location)  || eightImage.frame.contains(location)  ) && fourthCorrectImage.frame.contains(location) && fourthSlotIsTaken > 0 && fourthSlotHasImageNumber > 0 {
                hasTakenFromFourthSlot = 1
            }

            if firstCorrectImage.frame.contains(location) && FirstImage.frame.contains(location) == false && secondImage.frame.contains(location) == false && thirdImage.frame.contains(location) == false && fourthImage.frame.contains(location) == false && fifthImage.frame.contains(location) == false && sixthImage.frame.contains(location) == false && seventhImage.frame.contains(location) == false && eightImage.frame.contains(location) == false {
                firstSlotIsTaken = 0
            }
            if secondCorrectImage.frame.contains(location) && FirstImage.frame.contains(location) == false && secondImage.frame.contains(location) == false && thirdImage.frame.contains(location) == false && fourthImage.frame.contains(location) == false && fifthImage.frame.contains(location) == false && sixthImage.frame.contains(location) == false && seventhImage.frame.contains(location) == false && eightImage.frame.contains(location) == false {
                secondSlotIsTaken = 0
            }
            if thirdCorrectImage.frame.contains(location) && FirstImage.frame.contains(location) == false && secondImage.frame.contains(location) == false && thirdImage.frame.contains(location) == false && fourthImage.frame.contains(location) == false && fifthImage.frame.contains(location) == false && sixthImage.frame.contains(location) == false && seventhImage.frame.contains(location) == false && eightImage.frame.contains(location) == false {
                thirdSlotIsTaken = 0
            }
            if fourthCorrectImage.frame.contains(location) && FirstImage.frame.contains(location) == false && secondImage.frame.contains(location) == false && thirdImage.frame.contains(location) == false && fourthImage.frame.contains(location) == false && fifthImage.frame.contains(location) == false && sixthImage.frame.contains(location) == false && seventhImage.frame.contains(location) == false && eightImage.frame.contains(location) == false {
                fourthSlotIsTaken = 0
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches) {
            let location = touch.location(in: self.view)

               if imageSelected == 1 {
                FirstImage.center = location
            }
               if imageSelected == 2 {
                secondImage.center = location
            }
            if imageSelected == 3 {
                thirdImage.center = location
            }
            if imageSelected == 4 {
                fourthImage.center = location
            }
            if imageSelected == 5 {
                fifthImage.center = location
            }
            if imageSelected == 6 {
                sixthImage.center = location
            }
            if  imageSelected == 7 {
                seventhImage.center = location
            }
            if imageSelected == 8 {
                eightImage.center = location
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches) {
            let location = touch.location(in: self.view)

            if firstCorrectImage.frame.contains(location) && firstSlotIsTaken == 0 && hasTakenFromSecondSlot == 0 && hasTakenFromThirdSlot == 0 && hasTakenFromFourthSlot == 0  {
                if imageSelected > 0 {
                    audioPlayerOne.play()
                }
                firstSlotIsTaken = 1
                if imageSelected == 1 {
                    FirstImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 1
                }
                if imageSelected == 2 {
                    secondImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 2}
                if imageSelected == 3 {
                    thirdImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 3}
                if imageSelected == 4 {
                    fourthImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 4}
                if imageSelected == 5 {
                    fifthImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 5}
                if imageSelected == 6 {
                    sixthImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 6}
                if imageSelected == 7 {
                    seventhImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 7}
                if imageSelected == 8 {
                    eightImage.center = firstCorrectImage.center
                    firstSlotHasImageNumber = 8}

            } else { if secondCorrectImage.frame.contains(location) && secondSlotIsTaken == 0 && hasTakenFromFirstSlot == 0 && hasTakenFromThirdSlot == 0 && hasTakenFromFourthSlot == 0  {
                if imageSelected > 0 {
                    audioPlayerOne.play()
                }
                secondSlotIsTaken = 1
                if imageSelected == 1 {
                    FirstImage.center = secondCorrectImage.center
                    secondSlotHasImageNumber = 1}
                if imageSelected == 2 {
                    secondImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 2}
                if imageSelected == 3 {
                    thirdImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 3}
                if imageSelected == 4 {
                    fourthImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 4}
                if imageSelected == 5 {
                    fifthImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 5}
                if imageSelected == 6 {
                    sixthImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 6}
                if imageSelected == 7 {
                    seventhImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 7}
                if imageSelected == 8 {
                    eightImage.center = secondCorrectImage.center
                secondSlotHasImageNumber = 8}
            } else {  if thirdCorrectImage.frame.contains(location) && thirdSlotIsTaken == 0 && hasTakenFromSecondSlot == 0 && hasTakenFromFirstSlot == 0 && hasTakenFromFourthSlot == 0  {
                if imageSelected > 0 {
                    audioPlayerOne.play()
                }
                thirdSlotIsTaken = 1
                if imageSelected == 1 {
                    FirstImage.center = thirdCorrectImage.center
                    thirdSlotHasImageNumber = 1}
                if imageSelected == 2 {
                    secondImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 2}
                if imageSelected == 3 {
                    thirdImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 3}
                if imageSelected == 4 {
                    fourthImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 4}
                if imageSelected == 5 {
                    fifthImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 5}
                if imageSelected == 6 {
                    sixthImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 6}
                if imageSelected == 7 {
                    seventhImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 7}
                if imageSelected == 8 {
                    eightImage.center = thirdCorrectImage.center
                thirdSlotHasImageNumber = 8}
            } else {  if fourthCorrectImage.frame.contains(location) && fourthSlotIsTaken == 0 && hasTakenFromFirstSlot == 0 && hasTakenFromSecondSlot == 0 && hasTakenFromThirdSlot == 0 {
                if imageSelected > 0 {
                    audioPlayerOne.play()
                }
                fourthSlotIsTaken = 1
                if imageSelected == 1 {
                    FirstImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 1
                    }
                if imageSelected == 2 {
                    secondImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 2
                }
                if imageSelected == 3 {
                    thirdImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 3
                }
                if imageSelected == 4 {
                    fourthImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 4
                }
                if imageSelected == 5 {
                    fifthImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 5
                }
                if imageSelected == 6 {
                    sixthImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 6
                }
                if imageSelected == 7 {
                    seventhImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 7
                }
                if imageSelected == 8 {
                    eightImage.center = fourthCorrectImage.center
                    fourthSlotHasImageNumber = 8
               }

                }  else {
                UIView.animate(withDuration: 0.2, delay: 0, options: UIViewAnimationOptions(rawValue: UInt(0)), animations: ({
                    self.audioPlayerTwo.play()
                    if self.hasTakenFromFourthSlot == 1 {
                        self.hasTakenFromFourthSlot = 0
                        self.fourthSlotIsTaken = 0
                        self.fourthSlotHasImageNumber = 0
                    }
                    if self.hasTakenFromThirdSlot == 1 {
                        self.hasTakenFromThirdSlot = 0
                        self.thirdSlotIsTaken = 0
                        self.thirdSlotHasImageNumber = 0
                    }
                    if self.hasTakenFromSecondSlot == 1 {
                        self.hasTakenFromSecondSlot = 0
                        self.secondSlotIsTaken = 0
                        self.secondSlotHasImageNumber = 0
                    }
                    if self.hasTakenFromFirstSlot == 1 {
                        self.hasTakenFromFirstSlot = 0
                        self.firstSlotIsTaken = 0
                        self.firstSlotHasImageNumber = 0
                    }
                    self.getBackToInitialPosi()
                }), completion: nil)
            }

                }}}}

        if firstSlotHasImageNumber == 0 {
            firstSlotIsTaken = 0
        }
        if secondSlotHasImageNumber == 0 {
            secondSlotIsTaken = 0
        }
        if thirdSlotHasImageNumber == 0 {
            thirdSlotIsTaken = 0
        }
        if fourthSlotHasImageNumber == 0 {
            fourthSlotIsTaken = 0
        }
        imageSelected = 0



    }

    func getBackToInitialPosi() {

        if self.imageSelected == 1 {
            self.FirstImage.center = self.initialPosi }
        if self.imageSelected == 2 {
            self.secondImage.center = self.initialPosiSecond }
        if self.imageSelected == 3 {
            self.thirdImage.center = self.initialPosiThird }
        if self.imageSelected == 4 {
            self.fourthImage.center = self.initialPosiFourth }
        if self.imageSelected == 5 {
            self.fifthImage.center = self.initialPosiFifth }
        if self.imageSelected == 6 {
            self.sixthImage.center = self.initialPosiSixth }
        if self.imageSelected == 7 {
            self.seventhImage.center = self.initialPosiSeventh }
        if self.imageSelected == 8 {
            self.eightImage.center = self.initialPosiEigth }
        imageSelected = 0
    }

    func resetImages() {
        hasTakenFromFirstSlot = 0
        hasTakenFromSecondSlot = 0
        hasTakenFromThirdSlot = 0
        hasTakenFromFourthSlot = 0
        imageSelected = 0
        firstSlotIsTaken = 0
        secondSlotIsTaken = 0
        thirdSlotIsTaken = 0
        fourthSlotIsTaken = 0
        firstSlotHasImageNumber = 0
        secondSlotHasImageNumber = 0
        thirdSlotHasImageNumber = 0
        fourthSlotHasImageNumber = 0
    }

我不明白为什么 down-voted 这个问题的人在我发布这个问题后 30 秒就真的做了,而他们显然没有阅读它?也许应该在发布问题后添加一个 cool-down 计时器,以防止此类人像那样伤害社区。

无论如何,我设法解决了它,所以发布解决方案以防将来对某人有所帮助。

我所要做的就是添加使用 UITrackingRunLoopMode 更新 UILabel 的计时器,如下所示:

showGameTimeTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(showTime), userInfo: nil, repeats: true)

        RunLoop.main.add(showGameTimeTimer, forMode: RunLoopMode.UITrackingRunLoopMode)

        showGameTimeTimer.fire()

   func showTime(){
          globalTimeLeftLabel.text = gameTimerString
    }

这阻止它在触发触摸时重置可拖动图像