viewWillAppear for subviews

Above answers are correct if your scrollview is not in the zoomed in state. In case if your scrollview can zoom above calculation won't work as you need to consider zoom too

here is the code

CGRect visibleRect;
               visibleRect.origin = self.mapScrollView.contentOffset;
                visibleRect.size = self.mapScrollView.bounds.size;

                float theScale = 1.0 / self.mapScrollView.zoomScale;
                visibleRect.origin.x *= theScale;
                visibleRect.origin.y *= theScale;
                visibleRect.size.width *= theScale;
                visibleRect.size.height *= theScale;
                if(CGRectIntersectsRect(visibleRect, btnPin.frame)){
                      ...
                }

Swift 3 solution

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let viewFrame = greenView.frame

    let container = CGRect(x: scrollView.contentOffset.x, y: scrollView.contentOffset.y, width: scrollView.frame.size.width, height: scrollView.frame.size.height)


    // We may have received messages while this tableview is offscreen
    if (viewFrame.intersects(container)) {
        // Do work here
        print("view is visible")
    }
    else{
        print("nope view is not on the screen")
    }
}

You have to do the calculation yourself. Implement scrollViewDidScroll: in your scroll view delegate and calculate manually which views are visible (e.g. by checking if CGRectIntersectsRect(scrollView.bounds, subview.frame) returns true.


A slight refinement. I wanted to know the amount of the view that was displayed in the scrollview:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
{
    // Figure out how much of the self.userFeedbackView is displayed.
    CGRect frame = CGRectIntersection(self.scrollView.bounds, self.userFeedbackView.frame);
    CGFloat proportion = (frame.size.height*frame.size.width)/(self.userFeedbackView.frameWidth*self.userFeedbackView.frameHeight);
    NSLog(@"%f; %@", proportion, NSStringFromCGRect(frame));
}