Search code examples
iosswiftxcodetimertouchesbegan

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


I have built an Ipad game with multiple view controllers, at the beginning of which (at the ROOT VC) it fires a timer to countdown from 2hrs. Running on XCODE 8.2.1 / Swift 3.

On a ViewController further down the line (6th or 7th), I have a mini-game where user drags and drops from 8 available UIImageViews into 4 other UIImageViews (kind of like empty slots) via TouchesBegan/TouchesMoved/TouchesEnded. (the UIImageViews are set by Interface Builder).

There is a label on the top of the screen (with UserInteraction = disabled) that gets updated every 1 second to the current time left (on the 2hr countdown), via a Timer that is fired when the current View Controller loads (showgametimeTimer in the code below).

Problem is: this messes up the mini-game (the images fail to"lock" in their destination positions when user ends the drag with the finger) and this "glitch" only happens when the timer updating the label is running.

If i disable the timer though, everything works just fine and as expected.

So in some way the updating of the UILabel.text from the timer every 1 second, calls something that affects TouchesBegan and/or TouchesEnded.

The UILabel.text is on top of the screen, the objects to move are at the bottom. I tried setting boolean logic - ie timer.invalidate at beginning of touchesBegan, reinstate timer at end of TouchesEnded, to no avail, the issue remains.

The only way to fix it is by disabling the timer altogether for this View Controller.

I am adding the code although I think it will not really help to see the issue - I was just wondering if someone has ran into the same issue or has an idea of it's cause / how to fix? Beginner programmer here.

Many thanks

Relevant code:

    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
    }

Solution

  • I don't understand why the person who down-voted this question did it literally 30 seconds after I posted it when they clearly did not read it? Perhaps there should be a cool-down timer added after a question is posted preventing such people from hurting the community like that.

    Anyway, I managed to solve it, so posting the solution in case it helps someone in the future.

    All I had to do was add the timer that updated the UILabel with a UITrackingRunLoopMode like so:

    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
        }
    

    This prevented it from resetting the draggable images while touch was fired