2016-03-13 4 views
4

Я использую CADisplayLink как таймер в своем приложении. Я использую CADisplayLink, потому что мое приложение полагается HEAVILY на точность/точность CADisplayLink. NSTimer не является подходящей заменой в моем случае.Может ли работать CADisplayLink во время работы приложения в фоновом режиме?

Проблема в том, что иногда мне требуется CADisplayLink для запуска и вызова его селектора, в то время как приложение находится в фоновом режиме. Возможно ли это? Я понимаю, что CADisplayLink связан с частотой обновления пользовательского интерфейса приложения. Означает ли это, что, когда мое приложение находится в фоновом режиме, пользовательский интерфейс отсутствует, и поэтому невозможно использовать CADisplayLink в этом случае? Или можно каким-то образом использовать CADisplayLink, изменив цикл выполнения, который я добавляю, или изменив аргумент forMode? или, возможно, используя некоторые обманки GCD/work-around?

Примечание. Мое приложение использует AudioPlayer, и поэтому у меня есть возможности фона. Я могу запустить другой код в фоновом режиме. Просто чтобы проверить, я переключил свой CADisplayLink на NSTimer, и NSTimer уволил и вызвал его селектор, как я этого хотел. Я просто не могу получить CADisplayLink стрелять, и я не могу найти исчерпывающую документацию о возможности его использования в фоновом режиме

Вот мой текущий код, касающийся моей ссылки дисплея:

func beginTimer(){ 

    dispatch_async(dispatch_get_main_queue()){ 
     self.displayLink = CADisplayLink(target: self, selector: "update") 
     self.displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
    } 
} 

func update(){ 
    delegate?.executeCallback 
} 
+1

Я собирался упрекнуть вас за то, что вы не экспериментировали, чтобы узнать ответ на свой вопрос. Затем я более внимательно прочитал вашу дискуссию и решил, что вы не только должны экспериментировать, но и экспериментировать окончательно. Вы наверняка ответили на свой вопрос! – matt

+0

Спасибо @matt, я думаю, вы правы. Я просто надеялся, что оставил камень в камне. Знаете ли вы, что какой-либо таймер более-менее точно такой же, как CADisplayLink? Я не требую высокого уровня усмотрения между интервалами (т. Е. Допустимыми интервалами 0,5 секунды), я «только» требует очень последовательного или точного таймера. Один, который я могу гарантировать, будет срабатывать каждые 0,5 секунды с отметкой 1/2 секунды каждый раз. Это существует в iOS? – MikeG

+1

«Это существует в iOS» Нет, не совсем. В конце концов, даже CADisplayLink не является абсолютно регулярным. Кроме того, рассмотрите это: что, если он срабатывает, и основной поток в этот момент занят? Короче говоря, если вы не согласны принять определенную степень дрожания, вы станете очень несчастным кемпером, независимо от того, что вы используете. – matt

ответ

2

Это делает недокументированный смысл в том, что ваш обратный вызов на экране не вызывается в фоновом режиме, поскольку вы не должны рисовать в любом случае (на самом деле, если вы выполняете какую-либо работу графического процессора в фоновом режиме, ваше приложение убивается).

Итак, если вы уже используете аудио и фоновый режим, почему бы не попробовать реализовать свое время, выполнив аудио с помощью аудиоустройства remoteIO * и подсчитав выходные образцы вместо обновления экрана?

С помощью этого пути вы можете выбрать размер выходного буфера, эквивалентный или меньший, чем обычное обновление экрана 60 Гц.

Я думаю, что вы должны быть в состоянии получить сопоставимую (и, может быть, лучшую) временную точность, хотя в режиме с низким энергопотреблением и другими взаимодействиями с приложениями будут существовать предостережения, когда iOS может изменить размер вашего буфера из-под вас. Некоторые эксперименты будут необходимы.

* Я не думаю, что у AVAudioEngine есть эквивалент этого процедурного вывода.

+0

Спасибо за это прозрение, мне придется заглянуть в него. Есть ли способ сделать это в iOS, о котором вы знаете? Я не могу найти ни слова об этом. – MikeG