2014-10-22 3 views
1

Я хочу пробовать startRangingBeaconsSignal (который срабатывает каждые ~ 1 секунду) каждые 10 секунд, получая последний результат каждый раз.Пример сигнала каждые X секунд, отбросить все остальные

Из того, что я понимаю, это не цель функции дроссельной заслонки, которая, по-видимому, только посылаетNext, когда X времени прошло, не получив ничего.

Моя попытка ниже ограничивает сигнал только отправкой next раз в 10 секунд. Тем не менее, он не пропускает промежуточные сигналы, а вместо этого просто ставит их в очередь, чтобы их отправляли каждые 10 секунд. Итак, уже после того, как startRangingBeaconsSignal закончил отправку, мы все еще получаем от него капли.

Так что в сущности, мне нужен способ получить последний сигнал один раз каждые 10 секунд и игнорировать все остальные. Любые указатели в правильном направлении с благодарностью получили.

[[[[BeaconManager sharedInstance] startRangingBeaconsSignal] 
     sample:[RACSignal interval:10 onScheduler:[RACScheduler mainThreadScheduler]]] 
     subscribeNext:^(NSArray *beacons) { 
      // do something with beacons array 
     } 
    ]; 

Заранее благодарим за это и извинения за мою изворотливую терминологию.

+0

«Тем не менее, он не пропускает промежуточные сигналы, а вместо этого просто ставит их в очередь, чтобы их отправляли раз в 10 секунд. Поэтому, после того, как« startRangingBeaconsSignal »завершил отправку, мы по-прежнему получаем от него капли», , Попробуйте минимальное воспроизведение этого - это не так, как работает «образец». Он делает именно то, что вы описываете, - что вы делаете в 'subscribeNext'? –

ответ

0

я наконец нашел, что правильное решение заключается в использовании sample: и интервал установлен, как часто вы хотите (сюрприз сюрприз) «образец», сигнал:

/* countingUpwardsSignal is simply a signal returning x, x+1, x+2, and so on */ 

NSDate *startDate = [NSDate date]; 
RACSignal *countingUpwardsSignal = [[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] 
    startWith:startDate] 
    map:^id (NSDate *newDate) { 
     return @((int)[newDate secondsLaterThan:startDate]); 
    }]; 


/* fiveSecondsSampleSignal fires once every five seconds, 
    it is used to gate our subscription to countingUpwardsSignal: */ 

RACSignal *fiveSecondsSampleSignal = [RACSignal interval:5 onScheduler:[RACScheduler mainThreadScheduler]]; 

/* we combine the frequency of fiveSecondsSampleSignal to pull 
    the latest value from countingUpwardsSignal: */ 
[[countingUpwardsSignal sample:fiveSecondsSampleSignal] subscribeNext:^(id x) { 
    NSLog (@"x: %@", x); 
}]; 

Который возвращает:

x: 5 
x: 10 
x: 15 
x: 20 
x: 25 
x: 30 
x: 35 
x: 40 

Это именно то, что мне нужно.

EDIT: Фактически, как указывалось, это было точно так же, как и исходный код, который я опубликовал .. duh. Проблема с исходным кодом заключалась в том, что когда thestartRangingBeaconsSignal остановил стрельбу, sample: просто продолжал бы возвращать последнее полученное «следующее» снова и снова, поэтому я получал дубликаты. Решение было filter на основе третьего сигнала isRangingSignal, который остановил бы дублирующие достигающие абоненту:

@weakify(self); 
[[[[[BeaconManager sharedInstance] startRangingBeaconsSignal] 
    sample:[RACSignal interval:10 onScheduler:[RACScheduler mainThreadScheduler]]] 
    filter:^BOOL (id value) { 
     // HERE we check the value of isRangingSignal - if it's stopped, filter NO. 
     NSNumber *isRanging = [[BeaconManager sharedInstance] isRangingSignal].first; 
     return isRanging.boolValue; 
    }] 
    subscribeNext:^(NSArray *beacons) { 
     NSLog(@"Received beacons: %i", beacons.count); 
    } 
]; 
+0

Разве это не тот код, который вы отправили в исходном вопросе? –

+0

Должна быть какая-то другая ошибка в исходной проблеме, которая означала, что я не видел эффекта, который я ожидал с помощью 'sample:' –

+0

Обновлено, чтобы включить фактическое исправление. лол. –

1

Мы делаем что-то подобное here. Я не уверен, что это лучший подход, но он действительно работает.

В принципе, настройте повторяющийся сигнал с интервалом в 1 секунду и на нем будет take: 10, чтобы он автоматически останавливался. Затем сделайте map на следующих событиях из этого сигнала, игнорируя отправленные вами значения. Внутри метода map возвратите новый сигнал, который представляет работу, которую вы хотите выполнить. Затем вы можете просто switchToLatest подписаться на объекты, отправленные каждым из этих сигналов.

+0

Спасибо Ash - но я не уверен, что это правильно ответит на вопрос. То, что вы предлагаете, будет выполнять каждую секунду каждую секунду в течение 10 секунд, а затем останавливаться - я думаю? На самом деле то, о чем я спрашивал, было: скажем, у вас есть сигнал A, который срабатывает с перерывами (примерно каждый второй или второй) до сих пор до бесконечности. Нам нужно пробовать сигнал А каждые 10 секунд и извлекать из него все, что было последним значением в этой точке. Все остальное, отправленное с момента удаления последнего образца. –

+0

Так сказать Сигнал A срабатывает каждую секунду, отправляя [A, B, C, D, E, F, G, H, I, J, K, L], если мы подписываемся на него, мы хотим получить A, а затем (10 секунд спустя) К. Все остальное отбрасывается. –

+0

Я думаю, что то, что я ищу, может быть достигнуто с помощью combLatestWith :, Я отправлю сообщение, если я получу его работу. –

1

So throttle: - это в значительной степени то, что вы хотите. Из документации:

Посылает next S, только если мы не получим другой next в interval секунд.

Если получено next, а затем получено еще next, прежде чем interval секунд прошло, первое значение будет отброшено.

После того, как прошли interval секунд с момента последнего next был послан, самым последний next передается на планировщик, что значение было первоначально полученным. Если в то время + [RACScheduler currentScheduler] был нулем, используется частный планировщик фона.

Возвращает сигнал, который посылает дросселирование и задержку next событий. Завершение и ошибки всегда отправляются немедленно.

Таким образом, вы можете связать throttle: и distinctUntilChanged, чтобы получать самые свежие значения.

0

Это один случай, когда вы не хотите, чтобы душить, чтобы уменьшить сложность кода. К сожалению, BTLE не так эффективен, как когда-то надеялся. Таким образом, вы должны вручную обработать начальное ранжирование и начать ранжирование звонков самостоятельно. Звонки на CoreBluetooth по-прежнему происходят и расходуют время автономной работы. Это эквивалентно тому, чтобы делать посторонние GPS-звонки на каждый метр и «бросать» их, потому что вам нужно всего 10 метров. Или опрос сервера каждые 0,1 секунды, но только ответ на 10-й.

+0

Это хороший момент, спасибо –

Смежные вопросы