2016-08-29 219 views
0

我知道我可以使用followign语法(How to program a delay in Swift 3)的斯威夫特3延迟部分代码里面SWIFT 3延时:创建一个循环

let when = DispatchTime.now() + 2 // change 2 to desired second delay. 
DispatchQueue.main.after(when: when) { 
// run your code with delay 
} 

或者类似的帖子:How to create dispatch queue in Swift 3

然而,这些不是我可以使用的延迟方法。我需要在循环中插入一个延迟。例如,假设有一个标签组件和一个按钮。当我点击该按钮时,我希望标签连续显示循环变量:

@IBOutlet weak var showIntegers: UILabel! 

@IBAction func countNums(_ sender: AnyObject) { 

    for i in 1...5 { 
     showIntegers.text = String(i) 
     //delay code here, sleep(1) doesn't work 
    } 
} 

我用睡眠作为延迟但随后的应用休眠5秒,然后显示5.我看不到1,2,连续3秒,4秒和5秒延迟1秒。

我也弄不清楚如何在循环内部使用DispatchQueue类。感谢您的帮助提前。

+1

我会给你一个非常重要的建议 - 不要插入循环中的延迟。无论何时你认为你需要“睡眠(...)”,你都应该真正思考如何在不阻止等待的情况下写入函数。 – Sulthan

+3

我不明白你想暂停循环的原因。但是一般来说,你不应该阻塞主线程(IBAction会在主线程中被触发)。总是有一个更好的解决方案。您需要学会处理异步事件并在正确的时间对其进行响应。 –

+0

@M_G谢谢你的建议,但我没有要求建议,如果你知道如何在这里插入延迟,我会很高兴,如果你分享... – Graeme

回答

2

看来你正在寻找类似于我使用的东西。

请注意,我不使用DispatchQueue,而是一个更简单的计时器:

@IBAction func countNums(_ sender: AnyObject) { 
    for i in 1...5 { 
     Timer.scheduledTimer(timeInterval: Double(i - 1), // first timer triggers immediately, the others with 1 second delay from the previous timer 
          target: self, 
          selector: #selector(...myFunc(_:)), // please define here your func to call after the timer has triggered (see example below) 
          userInfo: i, // pass here the value that will be read inside the method myFunc 
          repeats: false)) 
    } 
} 

// method called when the timer triggers 
func myFunc(_ timer: Timer) { 
    guard let index = timer.userInfo as? Int else { return } 
    showIntegers(index) 
} 

// finally, actual action 
fun showIntegers(_ i: Int) { 
    showIntegers.text = String(i) 
} 

另外请注意,您可以合并两个功能showIntegersmyFunc:我已经把他们分开,因为,在我的意见,代码看起来更清晰这种方式。

6

sleep将无法​​正常工作,因为GUI需要一些时间才能更新,但是您在更新标签后立即立即睡眠主队列。您的应用程序在这段时间内没有响应,标签会从0跳到5,偶尔会有一些变化。

使用大中央调度async_after代替(曾经是斯威夫特2 dispatch_after):

@IBAction func countNums(_ sender: AnyObject) { 
    for i in 1...5 { 
     // Always update your GUI on the main thread 
     DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) { 
      self.showIntegers.text = "\(i)" 
     } 
    } 
}