这样好吗?
- (RACSignal *)deferRefreshSignalUntilScrollViewIsNotBusy:(RACSignal *)infiniteSignal
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
__block BOOL disposed = NO;
RACDisposable *disposable = [infiniteSignal subscribeNext:^(id originalValue) {
dispatch_repeated(0.0, 0.5, dispatch_get_main_queue(), ^(BOOL *stop) {
BOOL scrollViewIsBusy = self.scrollView.isTracking
|| self.scrollView.isDecelerating
|| self.scrollView.isDragging
|| _flags.animatingArticlePageScroller;
*stop = disposed;
if(!scrollViewIsBusy)
{
[subscriber sendNext:originalValue];
*stop = YES;
}
});
}];
return [RACDisposable disposableWithBlock:^{
[disposable dispose];
disposed = YES;
}];
}];
}
static void dispatch_repeated_internal(dispatch_time_t firstPopTime, double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop))
{
__block BOOL shouldStop = NO;
dispatch_time_t nextPopTime = dispatch_time(firstPopTime, (int64_t)intervalInSeconds * NSEC_PER_SEC);
dispatch_after(nextPopTime, queue, ^{
work(&shouldStop);
if(!shouldStop)
{
dispatch_repeated_internal(nextPopTime, intervalInSeconds, queue, work);
}
});
}
void dispatch_repeated(double delay, double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop))
{
dispatch_time_t firstPopTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)delay * NSEC_PER_SEC);
dispatch_repeated_internal(firstPopTime, intervalInSeconds, queue, work);
}
重要的是不要一直轮询滚动视图值。只有当你现在有一个新值时才进行轮询。
答案 0 :(得分:3)
将滚动视图的委托连接到self
(假设self
是UIViewController
的子类)
将此代码添加到self
...当滚动视图滚动时,此信号返回@YES
。它会在停止后返回@NO
。
- (RACSignal *)makeScrollViewSignal
{
RACSignal *didScroll = [self rac_signalForSelector:@selector(scrollViewDidScroll:) fromProtocol:@protocol(UIScrollViewDelegate)];
RACSignal *willDrag = [self rac_signalForSelector:@selector(scrollViewWillBeginDragging:) fromProtocol:@protocol(UIScrollViewDelegate)];
RACSignal *didDrag = [[self rac_signalForSelector:@selector(scrollViewDidEndDragging:willDecelerate:) fromProtocol:@protocol(UIScrollViewDelegate)] filter:^BOOL(RACTuple *tuple) {
return [tuple.second isEqualToNumber:@NO];
}];
RACSignal *didDecelerate = [self rac_signalForSelector:@selector(scrollViewDidEndDecelerating:) fromProtocol:@protocol(UIScrollViewDelegate)];
return [RACSignal merge:@[[didScroll mapReplace:@YES],
[willDrag mapReplace:@YES],
[didDrag mapReplace:@NO],
[didDecelerate mapReplace:@NO],
]];
}
next
,... 感谢Justin Spahr-Summers提供解决方案!
__block BOOL isScrolling = NO;
[self.scrollingSignal subscribeNext:^(NSNumber *isScrollingNumber) {
isScrolling = [isScrollingNumber boolValue];
}];
// your signal here
[[self.timerSignal throttle:INFINITY valuesPassingTest:^BOOL(id next) {
return isScrolling;
}] subscribeNext:^(NSNumber *timeInterval) {
// your work here
[self log:[NSString stringWithFormat:@"Timer: %ld", [timeInterval integerValue]]];
}];
next
,... 子类RACQueueScheduler
@interface DelayedScheduler : RACQueueScheduler
@property (nonatomic, strong) dispatch_queue_t delayQueue;
@property (nonatomic, strong) RACDisposable *delayDisposable;
@end
@implementation DelayedScheduler
+ (instancetype)delayedSchedulerWithSignal:(RACSignal *)signal
{
dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
DelayedScheduler *obj = [[self alloc] initWithName:@"com.ReactiveCocoa.RACScheduler.delayedMainThreadScheduler" queue:queue];
obj.delayQueue = queue;
obj.delayDisposable = [signal subscribeNext:^(NSNumber *delayEnabled) {
if ([delayEnabled boolValue]) {
dispatch_suspend(obj.queue);
} else {
dispatch_resume(obj.queue);
}
} error:^(NSError *error) {
dispatch_resume(obj.queue);
obj.delayDisposable = nil;
} completed:^{
dispatch_resume(obj.queue);
obj.delayDisposable = nil;
}];
return obj;
}
- (void)dealloc
{
[self.delayDisposable dispose];
}
@end
然后更改您的信号以在新的调度程序上传递
DelayedScheduler *delayed = [DelayedScheduler delayedSchedulerWithSignal:self.scrollingSignal];
[[self.timerSignal deliverOn:delayed] subscribeNext:^(NSNumber *timeInterval) {
dispatch_async(dispatch_get_main_queue(), ^{
[self log:[NSString stringWithFormat:@"%@", timeInterval]];
});
}];
将此添加到viewDidLoad
...
[[self makeScrollViewSignal] subscribeNext:^(NSNumber *isScrolling) {
if ([isScrolling boolValue]) {
dispatch_suspend(self.queue);
} else {
dispatch_resume(self.queue);
}
}];
// Your signal here... change the `self.timerSignal` to anything else
[self.timerSignal subscribeNext:^(NSNumber *timeInterval) {
dispatch_async(self.queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// TODO: add your code here...
[self log:[NSString stringWithFormat:@"%@", timeInterval]];
});
});
}];
答案 1 :(得分:2)
出于好奇,为什么不将自己(或其他一些合适的对象)作为UIScrollViewDelegate提供给滚动视图,并使用
[self rac_signalForSelector:@selector(scrollViewDidEndScrollingAnimation:)
fromProtocol:@protocol(UIScrollViewDelegate)]
获取滚动视图滚动时通知您的信号?