Respostas:
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
func sayHello()
{
NSLog("hello World")
}
Lembre-se de importar a Fundação.
Swift 4:
var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)
@objc func sayHello()
{
NSLog("hello World")
}
NSTimer
retém seu destino, então, com essa configuração, se helloWorldTimer
é uma propriedade self
você tem um ciclo de retenção, onde self
retém helloWorldTimer
e helloWorldTimer
retém self
.
Se tiver como objetivo a versão 10 e superior do iOS, você pode usar a renderização baseada em bloco de Timer
, que simplifica os ciclos de referência fortes em potencial, por exemplo:
weak var timer: Timer?
func startTimer() {
timer?.invalidate() // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
// do something here
}
}
func stopTimer() {
timer?.invalidate()
}
// if appropriate, make sure to stop your timer in `deinit`
deinit {
stopTimer()
}
Embora Timer
seja geralmente melhor, para fins de integridade, devo observar que você também pode usar o temporizador de despacho, que é útil para agendar temporizadores em threads de fundo. Com temporizadores de despacho, uma vez que são baseados em blocos, evita alguns dos desafios do ciclo de referência forte com o antigo target
/ selector
padrão de Timer
, desde que você use weak
referências.
Assim:
var timer: DispatchSourceTimer?
func startTimer() {
let queue = DispatchQueue(label: "com.domain.app.timer") // you can also use `DispatchQueue.main`, if you want
timer = DispatchSource.makeTimerSource(queue: queue)
timer!.schedule(deadline: .now(), repeating: .seconds(60))
timer!.setEventHandler { [weak self] in
// do whatever you want here
}
timer!.resume()
}
func stopTimer() {
timer?.cancel()
timer = nil
}
deinit {
self.stopTimer()
}
Para mais informações, consulte o a um temporizador Criando secção de Exemplos dispatch Fonte no despacho Fontes seção do Guia de Programação Concorrência.
Para Swift 2, consulte a revisão anterior desta resposta .
dispatch_after
. Ou uma não repetição NSTimer
.
Aqui está uma atualização para a NSTimer
resposta, para Swift 3 (no qual NSTimer
foi renomeado para Timer
) usando um encerramento em vez de uma função nomeada:
var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
(_) in
print("Hello world")
}
Se você pode permitir algum desvio de tempo, aqui está uma solução simples executando algum código a cada minuto:
private func executeRepeatedly() {
// put your code here
DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
self?.executeRepeatedly()
}
}
Basta executar executeRepeatedly()
uma vez e ele será executado a cada minuto. A execução para quando o objeto proprietário ( self
) é liberado. Você também pode usar um sinalizador para indicar que a execução deve parar.
No swift 3.0, o GCD foi refatorado:
let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
NSLog("Hello World")
}
timer.resume()
Isso é especialmente útil quando você precisa despachar em uma fila específica. Além disso, se você está planejando usar isso para atualização da interface do usuário, sugiro olhar CADisplayLink
como está sincronizado com a taxa de atualização da GPU.