 <p>You can fix this by creating local variables:</p> <pre><code>@IBAction func playButtonPressed(_ sender: Any) { var index = 0.0 var i = 0 var j = 0 while i &lt; sites.count { while j &lt; sites[i].count { let day = i let site = j DispatchQueue.main.asyncAfter(deadline: .now() + 1.0 * index) { self.plot(day: day, site: site) } j += 1 index += 1 } j = 0 i += 1 } } </code></pre> <p>Or, as pointed out by Martin R in <a href="http://stackoverflow.com/questions/31565832/pass-value-to-closure">Pass value to closure?</a>, you can "capture" these variables:</p> <pre><code>@IBAction func playButtonPressed(_ sender: Any) { var index = 0.0 var i = 0 var j = 0 while i &lt; sites.count { while j &lt; sites[i].count { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0 * index) { [i, j] in self.plot(day: i, site: j) } j += 1 index += 1 } j = 0 i += 1 } } </code></pre> <p>Or, personally, I'd probably use <code>for</code> loops to clean this up a bit:</p> <pre><code>@IBAction func playButtonPressed(_ sender: Any) { var delay = 0.0 for i in 0 ..&lt; sites.count { for j in 0 ..&lt; sites[i].count { DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [i, j] in self.plot(day: i, site: j) } delay += 1 } } } </code></pre>