I wanted a utility function on UIScrollView to automatically size the contentSize based on the content inside the scrollView. How is this?
#import "UIScrollView+UIScrollViewUtilities.h"
#import <objc/runtime.h>
static const int BOTTOM_CONTENT_OFFSET = 75;
@implementation UIScrollView (UIScrollViewUtilities)
- (void)setRecursiveSubviews:(NSMutableArray *)recursiveSubviews {
objc_setAssociatedObject(self, @selector(recursiveSubviews), recursiveSubviews, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableArray *)recursiveSubviews {
NSMutableArray *array = objc_getAssociatedObject(self, @selector(recursiveSubviews));
if (array == nil) {
array = [[NSMutableArray alloc] init];
[self setRecursiveSubviews:array];
}
return array;
}
- (void)autoAdjustContentSize {
[self autoAdjustContentSize:self];
}
/*
* This method is used to dynamically set the contentSize
* of a UIScrollView based on its content.
*/
- (void)autoAdjustContentSize:(UIView *)view {
// For all subviews of view passed in, add them to our
// recursiveSubviews array and call this method recursively
// to ensure we add all subviews (even grandchildren subviews)
for (UIView *subView in [view subviews]) {
NSMutableArray *array = [self recursiveSubviews];
[array addObject:subView];
[self setRecursiveSubviews:array];
[self autoAdjustContentSize:subView];
}
// Of all of our subviews found, figure out which one
// is the bottom-most element, and remember its y val
CGFloat currentBottomValue = 0;
for (UIView *subView in [self recursiveSubviews]) {
CGFloat thisElementsBottomValue = subView.frame.origin.y + subView.frame.size.height;
// Ignore UIViews because they are just blank space by themselves
if (![subView isMemberOfClass:[UIView class]] && thisElementsBottomValue > currentBottomValue) {
currentBottomValue = thisElementsBottomValue;
}
}
// Finally, update the contentSize of the scrollView based on the bottom most element found on screen
[self setContentSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width, currentBottomValue + BOTTOM_CONTENT_OFFSET)];
}
@end
UIView
(which you can size with auto-resizing constraints), then add thatUIView
to the scrollview. So the scroll view's content view has exactly one subview, and then it should work correctly. \$\endgroup\$