но что, если вы хотите переключаться между представлениями? Код остановится правильно?
Cing
5
@Cing зависит от того, о чем идет речь.
Antzi
1
Не забывайте, что NSTimerэто сохраняет свою цель, поэтому с этой настройкой, если helloWorldTimerэто свойство self, у вас есть цикл сохранения, в котором selfсохраняется helloWorldTimerи helloWorldTimerсохраняется self.
MANIAK_dobrii
@MANIAK_dobrii Не могли бы вы также прокомментировать, как разорвать цикл сохранения? Если ВК отклонен, но таймер не отменен, цикл все еще работает? Значит, вы должны одновременно отменить таймер, а затем закрыть представление, чтобы разорвать цикл?
Dave G
1
Для Swift 4 метод, для которого вы хотите получить селектор, должен быть доступен для Objective-C, поэтому атрибут @objc должен быть добавлен в объявление метода. например, `` @objc func sayHello () {} `` ``
Шамим Хоссейн,
136
Если нацелена на iOS версии 10 и выше, вы можете использовать блочное представление Timer, что упрощает потенциальные циклы сильных ссылок, например:
weakvar 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){[weakself]_in// do something here
}}func stopTimer(){
timer?.invalidate()}// if appropriate, make sure to stop your timer in `deinit`
deinit{
stopTimer()}
Хотя Timerв целом это лучше, для полноты картины я должен отметить, что вы также можете использовать таймер отправки, который полезен для планирования таймеров в фоновых потоках. С таймерами отправки, поскольку они основаны на блоках, они позволяют избежать некоторых проблем с сильным ссылочным циклом со старым target/ selectorшаблономTimer , если вы используете weakссылки.
Так:
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 {[weakself]in// do whatever you want here
}
timer!.resume()}func stopTimer(){
timer?.cancel()
timer =nil}deinit{self.stopTimer()}
Для получения дополнительной информации см Создание таймера раздел Отправка Источник примеров в источниках отправки секции параллелизмом Руководство по программированию.
как бы вы выбрали таймер однократного выполнения в рамках этого подхода?
Хуан Боэро
@JuanPabloBoero - Я бы не стал использовать этот подход в случае однократного пожара. Вы бы использовали dispatch_after. Или неповторяющийся NSTimer.
Роб
@Rob У меня есть метка счетчика на экране, которая обновляется каждую секунду функцией, и я использую приведенный выше код для увеличения счетчика и обновления текста метки. Но проблема, с которой я столкнулся, заключается в том, что моя переменная счетчика обновляется каждую секунду, но на экране не отображается последнее значение счетчика в моем UILabel.
Нагендра Рао,
Рао, это полезно для выполнения некоторых действий в фоновом потоке. Но ваши обновления пользовательского интерфейса должны происходить в основной очереди. Итак, либо запланируйте это в основном потоке, либо, по крайней мере, отправьте обновления пользовательского интерфейса обратно в основной поток.
Роб
1
Этот вопрос не относится к комментариям к этому ответу. Удалите свои комментарии выше и разместите свой вопрос. Но, короче говоря, вы обычно не заставляете приложение работать в фоновом режиме, а только заставляете его выглядеть так, как было. См. Stackoverflow.com/a/31642036/1271826 .
Роб
17
Вот обновление NSTimerответа для Swift 3 (в котором NSTimerбыл переименован в Timer) с использованием замыкания, а не именованной функции:
var timer =Timer.scheduledTimer(withTimeInterval:60, repeats:true){(_)in
print("Hello world")}
Если вы можете позволить себе некоторое время дрейфовать, вот простое решение, выполняющее некоторый код каждую минуту:
privatefunc executeRepeatedly(){// put your code here
DispatchQueue.main.asyncAfter(deadline:.now()+60.0){[weakself]inself?.executeRepeatedly()}}
Просто запустите executeRepeatedly()один раз, и он будет выполняться каждую минуту. Выполнение останавливается, когда объект-владелец ( self) освобождается. Вы также можете использовать флаг, чтобы указать, что выполнение должно быть остановлено.
let timer :DispatchSourceTimer=DispatchSource.makeTimerSource(flags:[], queue:DispatchQueue.main)
timer.scheduleRepeating(deadline:.now(), interval:.seconds(60))
timer.setEventHandler
{NSLog("Hello World")}
timer.resume()
Это особенно полезно, когда вам нужно выполнить отправку в определенной очереди. Кроме того, если вы планируете использовать это для обновления пользовательского интерфейса, я предлагаю проверить CADisplayLink, синхронизируется ли он с частотой обновления графического процессора.
Ответы:
Не забудьте импортировать Foundation.
Swift 4:
источник
NSTimer
это сохраняет свою цель, поэтому с этой настройкой, еслиhelloWorldTimer
это свойствоself
, у вас есть цикл сохранения, в которомself
сохраняетсяhelloWorldTimer
иhelloWorldTimer
сохраняетсяself
.Если нацелена на iOS версии 10 и выше, вы можете использовать блочное представление
Timer
, что упрощает потенциальные циклы сильных ссылок, например:Хотя
Timer
в целом это лучше, для полноты картины я должен отметить, что вы также можете использовать таймер отправки, который полезен для планирования таймеров в фоновых потоках. С таймерами отправки, поскольку они основаны на блоках, они позволяют избежать некоторых проблем с сильным ссылочным циклом со старымtarget
/selector
шаблономTimer
, если вы используетеweak
ссылки.Так:
Для получения дополнительной информации см Создание таймера раздел Отправка Источник примеров в источниках отправки секции параллелизмом Руководство по программированию.
Для Swift 2 см. Предыдущую версию этого ответа .
источник
dispatch_after
. Или неповторяющийсяNSTimer
.Вот обновление
NSTimer
ответа для Swift 3 (в которомNSTimer
был переименован вTimer
) с использованием замыкания, а не именованной функции:источник
Если вы можете позволить себе некоторое время дрейфовать, вот простое решение, выполняющее некоторый код каждую минуту:
Просто запустите
executeRepeatedly()
один раз, и он будет выполняться каждую минуту. Выполнение останавливается, когда объект-владелец (self
) освобождается. Вы также можете использовать флаг, чтобы указать, что выполнение должно быть остановлено.источник
Вы можете использовать
Timer
(swift 3)В selector () вы вводите имя своей функции
источник
Timer
...NSTimer
был переименованВ Swift 3.0 был произведен рефакторинг GCD:
Это особенно полезно, когда вам нужно выполнить отправку в определенной очереди. Кроме того, если вы планируете использовать это для обновления пользовательского интерфейса, я предлагаю проверить
CADisplayLink
, синхронизируется ли он с частотой обновления графического процессора.источник