Rotation handling in reactive style. Kinda complex =\
RACSignal *contentOffsetSignal = RACObserve(webView.scrollView, contentOffset);
RACSignal *contentSizeSignal = RACObserve(webView.scrollView, contentSize);
RACSignal *willRotateSignal = [self rac_signalForSelector:@selector(willRotateToInterfaceOrientation:duration:)];
// Sends @YES everytime orientation changes from portrait to landscape or vice-versa.
// will not send anything if changed from portrait to portrait upside down, for example.
RACSignal *orientationTypeChangedSignal = [[[willRotateSignal map:^(RACTuple *value) {
return value.first;
}] combinePreviousWithStart:@(self.interfaceOrientation)
reduce:^(NSNumber *previous, NSNumber *current) {
UIInterfaceOrientation previousOrientation = (UIInterfaceOrientation) [previous integerValue];
UIInterfaceOrientation currentOrientation = (UIInterfaceOrientation) [current integerValue];
BOOL orientationTypeNotChanged =
(UIInterfaceOrientationIsPortrait(previousOrientation) && UIInterfaceOrientationIsPortrait(currentOrientation)) ||
(UIInterfaceOrientationIsLandscape(previousOrientation) && UIInterfaceOrientationIsLandscape(currentOrientation));
return @(!orientationTypeNotChanged);
}]
filter:^BOOL(NSNumber *value) {
return value.boolValue;
}];
RACSignal *positionSignal = [[RACObserve(self, webView) sample:orientationTypeChangedSignal]
map:^(UIWebView *webView) {
CGPoint contentOffset = webView.scrollView.contentOffset;
CGSize contentSize = webView.scrollView.contentSize;
CGRect bounds = webView.scrollView.bounds;
CGFloat maxXOffset = contentSize.width - CGRectGetWidth(bounds);
return @( contentOffset.x / maxXOffset );
}];
RACSignal *willAnimateRotationSignal = [self rac_signalForSelector:@selector(willAnimateRotationToInterfaceOrientation:duration:)];
RAC(self.webView.scrollView, contentOffset) = [[[positionSignal combineLatestWith:RACObserve(self, webView)]
sample:willAnimateRotationSignal]
map:^(RACTuple *tuple) {
RACTupleUnpack(NSNumber *position, UIWebView *webView) = tuple;
CGSize contentSize = webView.scrollView.contentSize;
CGRect bounds = webView.scrollView.bounds;
CGFloat viewPortWidth = CGRectGetWidth(bounds);
CGFloat deltaX = viewPortWidth - 2 * ContentMargin;
CGFloat idealXOffset = (contentSize.width - viewPortWidth) * position.floatValue;
CGFloat newXOffset = (int)(idealXOffset / deltaX) * deltaX;
return [NSValue valueWithCGPoint:CGPointMake(newXOffset, 0)];
}];