TNLExample/TNLXImageViewController.m (126 lines of code) (raw):

// // TNLXImageViewController.m // TwitterNetworkLayer // // Created on 8/18/14. // Copyright © 2020 Twitter. All rights reserved. // #import <TwitterNetworkLayer/TwitterNetworkLayer.h> #import "TAPI.h" #import "TNLXImageSupport.h" #import "TNLXImageViewController.h" @import UIKit; @interface TNLXImageViewController () <UIScrollViewDelegate, TNLRequestDelegate> { UIScrollView *_scrollView; UIImageView *_contentImageView; } @property (nonatomic) TNLRequestOperation *activeOp; @end @implementation TNLXImageViewController - (instancetype)initWithImageEntity:(id<TAPIImageEntityModel>)imageEntity { id<TAPIImageEntityVariantModel> maxVariant = imageEntity.variants.lastObject; NSString *imageURLString = [NSString stringWithFormat:@"%@?format=%@&name=%@", imageEntity.baseURLString, imageEntity.format, maxVariant.name]; return [self initWithURL:[NSURL URLWithString:imageURLString] imageDimensions:maxVariant.dimensions]; } - (instancetype)initWithURL:(NSURL *)url imageDimensions:(CGSize)dims { if (self = [super initWithNibName:nil bundle:nil]) { _imageURL = url; _imageDimensions = dims; } return self; } - (void)viewDidLoad { [super viewDidLoad]; CGSize size = _imageDimensions; size.height /= [UIScreen mainScreen].scale; size.width /= [UIScreen mainScreen].scale; _contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; _contentImageView.contentMode = UIViewContentModeScaleAspectFit; _contentImageView.backgroundColor = [UIColor whiteColor]; _contentImageView.opaque = YES; _contentImageView.frame = (CGRect){ CGPointZero, size }; _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; _scrollView.contentSize = size; [_scrollView addSubview:_contentImageView]; _scrollView.opaque = YES; _scrollView.delegate = self; _scrollView.maximumZoomScale = 2.0; _scrollView.minimumZoomScale = MIN((CGFloat)1.0, (MIN(_scrollView.bounds.size.width, _scrollView.bounds.size.height) / MAX(size.width, size.height))); _scrollView.zoomScale = _scrollView.minimumZoomScale; UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)]; tapper.numberOfTapsRequired = 2; [_scrollView addGestureRecognizer:tapper]; [self.view addSubview:_scrollView]; } - (void)doubleTap:(UITapGestureRecognizer *)tapper { BOOL isMin = fabs(_scrollView.minimumZoomScale - _scrollView.zoomScale) < 0.05; [_scrollView setZoomScale:(isMin) ? _scrollView.maximumZoomScale : _scrollView.minimumZoomScale animated:YES]; } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return _contentImageView; } - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (!_activeOp && !_highResImage) { TNLXImageRequest *imageRequest = [TNLXImageRequest imageRequestWithURL:_imageURL]; _activeOp = [TNLRequestOperation operationWithRequest:imageRequest responseClass:[TNLXImageResponse class] configuration:nil delegate:self]; if (_blockingOperation) { [_activeOp addDependency:_blockingOperation]; } [[TNLRequestOperationQueue tnlx_imageRequestOperationQueue] enqueueRequestOperation:_activeOp]; } [self updateUI]; } - (void)updateUI { if (_highResImage) { _contentImageView.image = _highResImage; } else if (_lowResImage) { _contentImageView.image = _lowResImage; } else { _contentImageView.image = nil; } if (_contentImageView.image) { _contentImageView.alpha = (_activeOp) ? 0.5f : 1.0f; _contentImageView.backgroundColor = [UIColor whiteColor]; _scrollView.backgroundColor = [UIColor whiteColor]; } else { _contentImageView.backgroundColor = [UIColor grayColor]; _scrollView.backgroundColor = [UIColor grayColor]; } } - (void)setLowResImage:(UIImage *)lowResImage { _lowResImage = lowResImage; [self updateUI]; } - (void)setHighResImage:(UIImage *)highResImage { _highResImage = highResImage; [self updateUI]; } - (void)dealloc { [_activeOp cancelWithSource:@"navigated away"]; } #pragma mark - TNL - (void)tnl_requestOperation:(TNLRequestOperation *)op didCompleteWithResponse:(TNLXImageResponse *)response { assert([NSThread isMainThread]); _highResImage = response.image; _activeOp = nil; _blockingOperation = nil; [self updateUI]; } @end