Search code examples
iosswiftuikit

Animation typing text, swift


I'm trying to make an animation of writing text using this code:

extension UILabel {
    func animation(typing value: String, duration: Double) {
        for char in value {
            self.text?.append(char)
            RunLoop.current.run(until: Date() + duration)
        }
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    animationMainLabel.text = ""
    animationMainLabel.animation(typing: "[BE YOUR OWN GODDESS \nWITH STEYA COSMETICS.]", duration: 0.1)
}

It works well on the iPhone simulator but on a real iPhone the animation does not work. On a real iPhone, the text is simply displayed and that’s it. What's the matter?


Solution

  • Your code is blocking the main thread until it completes, which is freezing the UI (which runs continuously on the main thread). I'm not sure why it even runs on the simulator, but I suppose there are enough differences between the two platforms to explain it.

    You'll want to avoid blocking the main thread so the UI can update as you go.

    One way you could do that is with DispatchQueue's asyncAfter:

      func animation(typing value: String, duration: Double) {
        let semaphore = DispatchSemaphore(value: 1)
    
        DispatchQueue.global().async {
          for char in value {
            semaphore.wait()
            DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
              self.text?.append(char)
              semaphore.signal()
            }
          }
        }
      }
    

    The entire thing is wrapped in a background thread to avoid blocking the main thread.

    Using DispatchSemaphore ensures that the characters get appended one at a time in order by limiting when the asyncAfter gets called. The next one can only be called when the semaphore signal is called.

    Works nicely:

    typing animation gif