Reputation: 275
In my app I want to animate an array of Strings to give some instruction to users. My expectation is the first string fades in, maintains for seconds and fades out then the first string is removed from the array and the next shows and so on until the array gets empty. There is something wrong with my implementation however it's hard to debug (it seems the program would not be executed line by line), here is my code:
var text = [Text.text1, Text.text2]
@IBOutlet weak var paragraph: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
paragraph.alpha = 0
showText(text: text)
}
private func showText(text: [String]) {
if text.first == nil {
return
} else {
paragraph.text = text.first
UIView.animate(withDuration: 1.5, delay: 1.5, options: .curveEaseInOut, animations: {
self.paragraph.alpha = 1
}, completion: { (_) in
UIView.animate(withDuration: 1.5, delay: 0.5, options: .curveEaseInOut, animations: {
self.paragraph.alpha = 0
}, completion: { (_) in
self.text.remove(at: 0)
self.showText(text: text)
})
})
}
}
The problem is the first string shows three times and then I get an index out of range error. When I try setting breakpoints and click step over, it will skip the animation and completion blocks, and I don't know how to debug a function with a block as its parameter. And also even though I have
paragraph.text = text.first
after the first round, paragraph.text
has been the second string but still the first string shows.
Similarly, it seems my terminate condition doesn't work: after two iterations, I've noticed the count of the self.text
array has become 0, but the function didn't return, it goes to else...
if text.count == 0 {
return
} else { ... }
I'm a newbie and don't know how to debug blocks...
Upvotes: 1
Views: 349
Reputation: 318774
The problem is subtle and it's all in the second completion block. You have:
self.text.remove(at: 0)
self.showText(text: text)
You update the text
property but you then pass the local text
parameter which hasn't been changed.
Change the 2nd line to pass self.text
instead of just text
.
But referencing self.text
inside showText
negates to need to even have the text
parameter. Either write showText
to only use the text
property of the class or better, only reference the text
parameter. The latter has the advantage of not modifying the property.
To implement the latter option, change the two lines in the second completion block from:
self.text.remove(at: 0)
self.showText(text: text)
to just:
self.showText(text: Array(text[1...]))
Upvotes: 1