0

I am trying to display letters in a textView, one at a time, and with a delay but I am not able to get it right.

I want it to look like someone is typing it out. Here is my current code:

let delay = 2.0 * Double(NSEC_PER_SEC)
let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

let localmessage = message + "\n"

for letter in localmessage.characters {
        dispatch_after(dispatchTime, dispatch_get_main_queue(), {
            self.textView.text = self.textView.text + String(letter)

        })

   }
AtWork
  • 1,283
  • 1
  • 14
  • 34
user1079052
  • 3,803
  • 4
  • 30
  • 55

4 Answers4

4

You are using the same dispatchTime so all the characters will all be displayed at the same time. You need to increment the dispatchTime in your for loop to display the characters one at a time.

Try it like this:

let localmessage = message + "\n"

var myInt = 1

for letter in localmessage.characters {

    let delay = 2.0 * Double(NSEC_PER_SEC) * Double(myInt)
    let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

    dispatch_after(dispatchTime, dispatch_get_main_queue(), {
        self.textView.text = self.textView.text + String(letter)
    })

    myInt = myInt + 1
}
Carter
  • 3,053
  • 1
  • 17
  • 22
MSU_Bulldog
  • 3,501
  • 5
  • 37
  • 73
2

Here's how i would do it

let message = "hello world"
    var index:Double = 1.0
    let delayInSeconds = 0.5
    for letter in message.characters {
        runAfterDelay(delayInSeconds * index, block: {
            self.firstTextField.text = self.firstTextField.text! + String(letter)
        })
        index = index + 1
    }
}

func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), block)
}

The runAfterDelay function proves to be pretty handy in a lot of situations so I like to keep it around :)

LuKenneth
  • 2,197
  • 2
  • 18
  • 41
0

You can try use NSTimer, instead of GCD:

var index = 0
var timer = NSTimer()

    override func viewDidLoad() {
        super.viewDidLoad()

        timer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(ViewController.updateTextView), userInfo: nil, repeats: true)

    }

    func updateTextView() {

        let letter = localmessage.characters[index]

        self.textView.text = self.textView.text + String(letter)

        index++
        if index == localmessage.characters.count {
           timer.invalidate()
        }

    }
Anton Novoselov
  • 769
  • 2
  • 7
  • 19
0

Why not simply use a Timer?

class ViewController: UIViewController {

    @IBOutlet weak var textView: UITextView!

    let message = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."

    override func viewDidLoad() {
        super.viewDidLoad()
        self.typingTimer()
    }

    func typingTimer() {
        var localMessage = message
        Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { timer in
            if localMessage.characters.count > 0 {
                self.textView.text.append(localMessage.characters.remove(at: localMessage.characters.startIndex))
            } else {
                timer.invalidate()
            }
        })
    }

}
Søren Mortensen
  • 1,663
  • 1
  • 11
  • 25