paging in UIScrollView is a great feature, what I need here is to set the paging to a smaller distance, for example I want my UIScrollView to page less size that the UIScrol
This seemed to work a lot better for me:
UIScrollView Custom Paging
Here they are adding the scrollview (keeping it's paging niceness) as a subview to an ExtendedTouchView or subclass of UIVIew and overwriting the hit test method
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([self pointInside:point withEvent:event]) {
    if ([[self subviews] count] > 0) {
        //force return of first child, if exists
        return [[self subviews] objectAtIndex:0];
    } else {
        return self;
    }
}
return nil;
}
This did exactly whatI wanted with minimal code and headache.
The easiest way is to add this code
scrollView.clipsToBounds = false
scrollView.removeGestureRecognizer(scrollView.panGestureRecognizer)
view.addGestureRecognizer(scrollView.panGestureRecognizer)
You should disable paging and add a UIPanGestureRecognizer to your scroll view and handle the paging yourself.
- (void)viewDidLoad {
    [super viewDidLoad];
    CGRect viewRect = self.view.bounds; // View controller's view bounds
    theScrollView = [[UIScrollView alloc] initWithFrame:viewRect]; 
    theScrollView.scrollsToTop      = NO;
    theScrollView.pagingEnabled         = NO;
    theScrollView.delaysContentTouches  = NO;
    theScrollView.delegate = self;
    [self.view addSubview:theScrollView];
    UIPanGestureRecognizer * peter = [[[UIPanGestureRecognizer alloc] initWithTarget:self  
                                                                              action:@selector(handlePan:)]
                                       autorelease]; 
    [theScrollView addGestureRecognizer:peter]; 
}
-(void)handlePan:(UIPanGestureRecognizer*)recognizer{
    switch (recognizer.state) {
    case UIGestureRecognizerStateBegan:{
        // panStart and startPoint are instance vars for the viewContainer 
        panStart = theScrollView.contentOffset;
        startPoint = [recognizer locationInView:theScrollView]; 
        
        
        break;
    }
    case UIGestureRecognizerStateChanged:{
                    
        CGPoint newPoint = [recognizer locationInView:theScrollView];
        CGFloat delta = startPoint.x - newPoint.x;
        if ( abs(delta) > 2)
            theScrollView.contentOffset = CGPointMake( theScrollView.contentOffset.x + delta, 0); 
        
        CGFloat moveDelta = panStart.x - theScrollView.contentOffset.x;                               
        
        // current witdh should hold the currently displayed page/view in theScrollView
        if ( abs(moveDelta) > (currentWidth * 0.40)){
            panStart = theScrollView.contentOffset;
            startPoint = newPoint;
            
            //NSLog(@"delta is bigger"); 
            if ( moveDelta < 0 )
                [self incrementPageNumber]; // you should implement this method and present the next view
            else 
                [self decrementPageNumber]; // you should implement this method and present the previous view
   
            recognizer.enabled = NO; // disable further event until view change finish
                 
        }
        
        break; 
    }
        
    case UIGestureRecognizerStateEnded:
    case UIGestureRecognizerStateCancelled:
        recognizer.enabled = YES; 
        [self showDocumentPage:currentPage]; 
        
        break;
        
        
    default:
        break;
    }
}
Swift 4.1 solution that simplifies reusing:
/// Protocol that simplifies custom page size configuration for UIScrollView.
/// Sadly, can not be done better due to protocol extensions limitations - https://stackoverflow.com/questions/39487168/non-objc-method-does-not-satisfy-optional-requirement-of-objc-protocol
/// - note: Set `.decelerationRate` to `UIScrollViewDecelerationRateFast` for a fancy scrolling animation.
protocol ScrollViewCustomHorizontalPageSize: UIScrollViewDelegate {
    /// Custom page size
    var pageSize: CGFloat { get }
    /// Helper method to get current page fraction
    func getCurrentPage(scrollView: UIScrollView) -> CGFloat
    /// Helper method to get targetContentOffset. Usage:
    ///
    ///     func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    ///         targetContentOffset.pointee.x = getTargetContentOffset(scrollView: scrollView, velocity: velocity)
    ///     }
    func getTargetContentOffset(scrollView: UIScrollView, velocity: CGPoint) -> CGFloat
    /// Must be implemented. See `getTargetContentOffset` for more info.
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
}
extension ScrollViewCustomHorizontalPageSize {
    func getCurrentPage(scrollView: UIScrollView) -> CGFloat {
        return (scrollView.contentOffset.x + scrollView.contentInset.left) / pageSize
    }
    func getTargetContentOffset(scrollView: UIScrollView, velocity: CGPoint) -> CGFloat {
        let targetX: CGFloat = scrollView.contentOffset.x + velocity.x * 60.0
        var targetIndex = (targetX + scrollView.contentInset.left) / pageSize
        let maxOffsetX = scrollView.contentSize.width - scrollView.bounds.width + scrollView.contentInset.right
        let maxIndex = (maxOffsetX + scrollView.contentInset.left) / pageSize
        if velocity.x > 0 {
            targetIndex = ceil(targetIndex)
        } else if velocity.x < 0 {
            targetIndex = floor(targetIndex)
        } else {
            let (maxFloorIndex, lastInterval) = modf(maxIndex)
            if targetIndex > maxFloorIndex {
                if targetIndex >= lastInterval / 2 + maxFloorIndex {
                    targetIndex = maxIndex
                } else {
                    targetIndex = maxFloorIndex
                }
            } else {
                targetIndex = round(targetIndex)
            }
        }
        if targetIndex < 0 {
            targetIndex = 0
        }
        var offsetX = targetIndex * pageSize - scrollView.contentInset.left
        offsetX = min(offsetX, maxOffsetX)
        return offsetX
    }
}
Just conform to ScrollViewCustomPageSize protocol in your UIScrollView/UITableView/UICollectionView delegate and you are done, e.g.:
extension MyCollectionViewController: ScrollViewCustomPageSize {
    var pageSize: CGFloat {
        return 200
    }
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        targetContentOffset.pointee.x = getTargetContentOffset(scrollView: scrollView, velocity: velocity)
    }
}
For a fancy scrolling I also recommend to set collectionView.decelerationRate = UIScrollViewDecelerationRateFast
Swift 4.1, iOS11+:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    targetContentOffset.pointee = CGPoint(
        x: round(targetContentOffset.pointee.x / pageWidth) * pageWidth,
        y: targetContentOffset.pointee.y
    )
}
I had the same problem short ago. My aproach was to add a second UIScrollView to the scrollview. So you can switch to the page. On that page it seems than if the page is bigger than the screen. I hope it works also in your situation. ;-)
Sandro Meier