Bgerstle has uploaded a new change for review. https://gerrit.wikimedia.org/r/193292
Change subject: Fix iOS 6 image gallery rotation ...................................................................... Fix iOS 6 image gallery rotation Also: - modify project settings to cause compiler errors when declared methods aren't defined - fixed instances of above warning Bug: T90752 Change-Id: I24357d7f1636bda191e183489717cfcb8078839e --- M Wikipedia.xcodeproj/project.pbxproj A wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.h A wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.m M wikipedia/EventLogging/EventLoggingFunnel.m M wikipedia/View Controllers/Image Gallery/WMFImageGalleryViewController.m 5 files changed, 131 insertions(+), 55 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/ios/wikipedia refs/changes/92/193292/1 diff --git a/Wikipedia.xcodeproj/project.pbxproj b/Wikipedia.xcodeproj/project.pbxproj index b7c2089..d510d45 100644 --- a/Wikipedia.xcodeproj/project.pbxproj +++ b/Wikipedia.xcodeproj/project.pbxproj @@ -297,6 +297,8 @@ C42D947E1A937DAC00A4871A /* SavedArticlesFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C42D947D1A937DAC00A4871A /* SavedArticlesFetcher.m */; }; C42D94861A937DE000A4871A /* WMFBorderButton.m in Sources */ = {isa = PBXBuildFile; fileRef = C42D94831A937DE000A4871A /* WMFBorderButton.m */; }; C42D94871A937DE000A4871A /* WMFProgressLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = C42D94851A937DE000A4871A /* WMFProgressLineView.m */; }; + BCC185E81A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC185E71A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m */; }; + BCC185E91A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC185E71A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m */; }; C46FBA4B1A8530EE00C5730F /* Pods-acknowledgements.plist in Resources */ = {isa = PBXBuildFile; fileRef = C46FBA4A1A8530EE00C5730F /* Pods-acknowledgements.plist */; }; C90799BA1A8564C60044E13C /* WMFShareOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C90799B91A8564C60044E13C /* WMFShareOptionsViewController.m */; }; C913C89C1A94019A00BEEAF0 /* WMFSuggestedPagesFunnel.m in Sources */ = {isa = PBXBuildFile; fileRef = C913C89B1A94019A00BEEAF0 /* WMFSuggestedPagesFunnel.m */; }; @@ -817,6 +819,8 @@ C42D94831A937DE000A4871A /* WMFBorderButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WMFBorderButton.m; sourceTree = "<group>"; }; C42D94841A937DE000A4871A /* WMFProgressLineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMFProgressLineView.h; sourceTree = "<group>"; }; C42D94851A937DE000A4871A /* WMFProgressLineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WMFProgressLineView.m; sourceTree = "<group>"; }; + BCC185E61A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionViewFlowLayout+AttributeUtils.h"; sourceTree = "<group>"; }; + BCC185E71A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionViewFlowLayout+AttributeUtils.m"; sourceTree = "<group>"; }; C46FBA4A1A8530EE00C5730F /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Pods-acknowledgements.plist"; path = "../../../Pods/Target Support Files/Pods/Pods-acknowledgements.plist"; sourceTree = "<group>"; }; C90799B81A8564C60044E13C /* WMFShareOptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WMFShareOptionsViewController.h; path = ShareCard/WMFShareOptionsViewController.h; sourceTree = "<group>"; }; C90799B91A8564C60044E13C /* WMFShareOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WMFShareOptionsViewController.m; path = ShareCard/WMFShareOptionsViewController.m; sourceTree = "<group>"; }; @@ -1785,6 +1789,8 @@ BC86B93C1A929CC500B4C039 /* UICollectionViewFlowLayout+NSCopying.m */, BC86B93E1A929D7900B4C039 /* UICollectionViewFlowLayout+WMFItemSizeThatFits.h */, BC86B93F1A929D7900B4C039 /* UICollectionViewFlowLayout+WMFItemSizeThatFits.m */, + BCC185E61A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.h */, + BCC185E71A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m */, ); path = Categories; sourceTree = "<group>"; @@ -2788,6 +2794,7 @@ BCB66A0D1A85183000C7B1FE /* NSString+WMFHTMLParsing.m in Sources */, BCB669EE1A83F71C00C7B1FE /* MWKProtectionStatus.m in Sources */, BCB669F41A83F71C00C7B1FE /* MWKRecentSearchList.m in Sources */, + BCC185E91A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m in Sources */, 04BA48A21A80062F00CB5CAE /* UIFont+WMFStyle.m in Sources */, BCB669741A83F58600C7B1FE /* NSMutableDictionary+WMFMaybeSet.m in Sources */, 042BEAF01A92EE66002CF320 /* UIWebView+WMFTrackingView.m in Sources */, @@ -2937,6 +2944,7 @@ BC50C37F1A83C784006DC7AF /* WMFNetworkUtilities.m in Sources */, BCB58F441A890D9700465627 /* MWKImageInfo+MWKImageComparison.m in Sources */, BCB669AD1A83F6C400C7B1FE /* MWKSavedPageList.m in Sources */, + BCC185E81A9FA498005378F8 /* UICollectionViewFlowLayout+AttributeUtils.m in Sources */, 04B91AB718E4D5B200FFAA1C /* TabularScrollView.m in Sources */, 04C695D218ED213000D9F2DA /* UIScrollView+NoHorizontalScrolling.m in Sources */, 04E106381A3560A90046DC27 /* LeadImageTitleLabel.m in Sources */, @@ -3371,6 +3379,7 @@ "-Werror=switch", "-Werror=arc-retain-cycles", "-Werror=incompatible-pointer-types", + "-Werror=incomplete-implementation", ); WRAPPER_EXTENSION = app; }; @@ -3404,6 +3413,7 @@ "-Werror=switch", "-Werror=arc-retain-cycles", "-Werror=incompatible-pointer-types", + "-Werror=incomplete-implementation", ); WRAPPER_EXTENSION = app; }; diff --git a/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.h b/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.h new file mode 100644 index 0000000..b051322 --- /dev/null +++ b/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.h @@ -0,0 +1,43 @@ +// +// UICollectionViewFlowLayout+AttributeUtils.h +// Wikipedia +// +// Created by Brian Gerstle on 2/26/15. +// Copyright (c) 2015 Wikimedia Foundation. All rights reserved. +// + +#import <UIKit/UIKit.h> + +/** + * Utilities for getting layout attributes and index paths for items in a flow layout. + * @warning Most of these methods were naively implemented and only support layouts configured with a horizontal + * scrolling direction. + */ +@interface UICollectionViewFlowLayout (AttributeUtils) + +/// The @c NSIndexPath for the item closest to the current @c contentOffset of the receiver's @c collectionView. +- (NSIndexPath*)wmf_indexPathClosestToContentOffset; + +/** + * Sort an array of @c UICollectionViewLayoutAttribute objects by their distance to @c point in ascending order. + * @param attributes The @c UICollectionViewLayoutAttributes objects to sort. + * @param point A point within the @c contentSize of the receiver's @c collectionView. + * @return A sorted version of the given @c attributes array. + */ +- (NSArray*)wmf_sortAttributesByLeadingEdgeDistance:(NSArray*)attributes toPoint:(CGPoint)point; + +/** + * Get an array of the currently visible items' attributes, sorted by distance to @c point in ascending order. + * @param point A point within the @c contentSize of the receiver's @c collectionView. + * @return An array of @c UICollectionViewLayoutAttributes. + * @see -wmf_sortAttributesByLeadingEdgeDistance:toPoint + */ +- (NSArray*)wmf_layoutAttributesByDistanceToPoint:(CGPoint)point; + +/** + * Map the receiver's <code>collectionView.indexPathsForVisibleItems</code> into an array of their layout attributes. + * @return An array of @c UICollectionViewLayoutAttributes. + */ +- (NSArray*)wmf_layoutAttributesForVisibleIndexPaths; + +@end diff --git a/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.m b/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.m new file mode 100644 index 0000000..20d1d05 --- /dev/null +++ b/wikipedia/Categories/UICollectionViewFlowLayout+AttributeUtils.m @@ -0,0 +1,41 @@ +// +// UICollectionViewFlowLayout+AttributeUtils.m +// Wikipedia +// +// Created by Brian Gerstle on 2/26/15. +// Copyright (c) 2015 Wikimedia Foundation. All rights reserved. +// + +#import "UICollectionViewFlowLayout+AttributeUtils.h" +#import <BlocksKit/BlocksKit.h> + +@implementation UICollectionViewFlowLayout (AttributeUtils) + +- (NSIndexPath*)wmf_indexPathClosestToContentOffset +{ + return [[[self wmf_layoutAttributesByDistanceToPoint:self.collectionView.contentOffset] firstObject] indexPath]; +} + +- (NSArray*)wmf_sortAttributesByLeadingEdgeDistance:(NSArray*)attributes toPoint:(CGPoint)point +{ + return [attributes sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewLayoutAttributes* attr1, + UICollectionViewLayoutAttributes* attr2) { + float leadingEdgeDistance1 = fabsf(point.x - attr1.frame.origin.x); + float leadingEdgeDistance2 = fabsf(point.x - attr2.frame.origin.x); + return leadingEdgeDistance1 - leadingEdgeDistance2; + }]; +} + +- (NSArray*)wmf_layoutAttributesByDistanceToPoint:(CGPoint)point +{ + return [self wmf_sortAttributesByLeadingEdgeDistance:[self wmf_layoutAttributesForVisibleIndexPaths] toPoint:point]; +} + +- (NSArray*)wmf_layoutAttributesForVisibleIndexPaths +{ + return [self.collectionView.indexPathsForVisibleItems bk_map:^(NSIndexPath* path) { + return [self layoutAttributesForItemAtIndexPath:path]; + }]; +} + +@end diff --git a/wikipedia/EventLogging/EventLoggingFunnel.m b/wikipedia/EventLogging/EventLoggingFunnel.m index c20e511..cb0325d 100644 --- a/wikipedia/EventLogging/EventLoggingFunnel.m +++ b/wikipedia/EventLogging/EventLoggingFunnel.m @@ -31,10 +31,10 @@ { SessionSingleton *session = [SessionSingleton sharedInstance]; NSString *wiki = [session.site.language stringByAppendingString:@"wiki"]; - [self log:eventData forWiki:wiki]; + [self log:eventData wiki:wiki]; } --(void)log:(NSDictionary *)eventData forWiki:(NSString *)wiki +-(void)log:(NSDictionary *)eventData wiki:(NSString *)wiki { if ([SessionSingleton sharedInstance].sendUsageReports) { (void)[[EventLogger alloc] initAndLogEvent:[self preprocessData:eventData] diff --git a/wikipedia/View Controllers/Image Gallery/WMFImageGalleryViewController.m b/wikipedia/View Controllers/Image Gallery/WMFImageGalleryViewController.m index 2475517..b921a2c 100644 --- a/wikipedia/View Controllers/Image Gallery/WMFImageGalleryViewController.m +++ b/wikipedia/View Controllers/Image Gallery/WMFImageGalleryViewController.m @@ -22,6 +22,7 @@ #import "UICollectionViewFlowLayout+NSCopying.h" #import "UICollectionViewFlowLayout+WMFItemSizeThatFits.h" #import "UIViewController+Alert.h" +#import "UICollectionViewFlowLayout+AttributeUtils.h" // Model #import "MWKDataStore.h" @@ -42,7 +43,7 @@ #endif @interface WMFImageGalleryViewController () -<UIGestureRecognizerDelegate> +<UIGestureRecognizerDelegate, UICollectionViewDelegateFlowLayout> { MWKImageInfoFetcher *_imageInfoFetcher; AFHTTPRequestOperationManager *_imageFetcher; @@ -50,10 +51,10 @@ NSArray *_uniqueArticleImages; } -@property (nonatomic) BOOL didSetInitialItemSize; -@property (nonatomic) BOOL didPerformInitialLayout; @property (nonatomic) BOOL didApplyInitialVisibleImageIndex; +@property (nonatomic) NSUInteger preRotationVisibleImageIndex; +@property (nonatomic, weak, readonly) UICollectionViewFlowLayout *collectionViewFlowLayout; @property (nonatomic, weak, readonly) UIButton *closeButton; @property (nonatomic, getter=isChromeHidden) BOOL chromeHidden; @property (nonatomic, weak, readonly) UITapGestureRecognizer *chromeTapGestureRecognizer; @@ -184,6 +185,11 @@ return nil; } +- (NSUInteger)mostVisibleItemIndex +{ + return [self.collectionViewFlowLayout wmf_indexPathClosestToContentOffset].item; +} + #pragma mark - Networking & Persistence - (void)fetchImageInfo @@ -223,62 +229,34 @@ duration:(NSTimeInterval)duration { [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; - if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation) - == UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { - return; - } - - // need to capture visibleImageIndex before the animation, else collectionViewDelegate methods will throw it off - NSUInteger currentImageIndex = self.visibleImageIndex; - CGSize currentSize = self.view.bounds.size; - CGSize newBounds = CGSizeMake(currentSize.height, currentSize.width); + NSUInteger const currentImageIndex = [self mostVisibleItemIndex]; + ImgGalleryLog(@"Will scroll to %u after rotation animation finishes.", currentImageIndex); [UIView animateWithDuration:duration delay:0 - options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState + options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowAnimatedContent animations:^{ - self.collectionViewFlowLayout.itemSize = [self.collectionViewFlowLayout wmf_itemSizeThatFits:newBounds]; - } - completion:^ (BOOL finished) { - self.visibleImageIndex = currentImageIndex; - }]; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - // set this before, otherwise it won't be true inside other calls like viewDidLayoutSubviews - _didSetInitialItemSize = YES; - [self.collectionViewFlowLayout wmf_strictItemSizeToFit]; - [self applyChromeHidden:animated]; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - // assert that all the expected state transitions happened - NSParameterAssert(_didSetInitialItemSize); - NSParameterAssert(_didPerformInitialLayout); - NSParameterAssert(_didApplyInitialVisibleImageIndex); + [self.collectionViewFlowLayout invalidateLayout]; + } + completion:^(BOOL finished) { + [self setVisibleImageIndex:currentImageIndex animated:NO forceViewUpdate:YES]; + }]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - // reset item size once the collection view has been laid out - if (_didSetInitialItemSize && !_didPerformInitialLayout) { - _didPerformInitialLayout = YES; + if (!self.didApplyInitialVisibleImageIndex) { [self applyVisibleImageIndex:NO]; // only set the flag *after* the visible index has been updated, to make sure UICollectionViewDelegate // callbacks don't override it - _didApplyInitialVisibleImageIndex = YES; + self.didApplyInitialVisibleImageIndex = YES; } } - (void)viewDidLoad { [super viewDidLoad]; - // manually layout closeButton so we can programmatically increase it's hit size NSString* closeButtonTitle = WIKIGLYPH_X; @@ -377,15 +355,22 @@ - (void)applyVisibleImageIndex:(BOOL)animated { if ([self isViewLoaded]) { - [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:self.visibleImageIndex inSection:0] - atScrollPosition:UICollectionViewScrollPositionLeft - animated:animated]; + // can't use scrollToItem because it doesn't handle post-rotation scrolling well on iOS 6 + UICollectionViewLayoutAttributes* visibleImageAttributes = + [self.collectionViewFlowLayout layoutAttributesForItemAtIndexPath: + [NSIndexPath indexPathForItem:self.visibleImageIndex inSection:0]]; + [self.collectionView setContentOffset:visibleImageAttributes.frame.origin animated:animated]; } } - (void)setVisibleImageIndex:(NSUInteger)visibleImageIndex animated:(BOOL)animated { - if (visibleImageIndex == _visibleImageIndex) { return; } + [self setVisibleImageIndex:visibleImageIndex animated:animated forceViewUpdate:NO]; +} + +- (void)setVisibleImageIndex:(NSUInteger)visibleImageIndex animated:(BOOL)animated forceViewUpdate:(BOOL)force +{ + if (!force && visibleImageIndex == _visibleImageIndex) { return; } NSParameterAssert(visibleImageIndex < self.uniqueArticleImages.count); _visibleImageIndex = visibleImageIndex; [self applyVisibleImageIndex:animated]; @@ -414,15 +399,11 @@ #pragma mark Delegate -- (void)collectionView:(UICollectionView *)collectionView - willDisplayCell:(UICollectionViewCell *)cell - forItemAtIndexPath:(NSIndexPath *)indexPath +- (CGSize)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout + sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - // only apply after initial visible index has been set - if (_didApplyInitialVisibleImageIndex) { - // silently update the visible image index (i.e. do *not* use the setter!) - _visibleImageIndex = indexPath.item; - } + return [self.collectionViewFlowLayout wmf_itemSizeThatFits:self.view.bounds.size]; } #pragma mark DataSource @@ -434,6 +415,7 @@ (WMFImageGalleryCollectionViewCell*) [collectionView dequeueReusableCellWithReuseIdentifier:WMFImageGalleryCollectionViewCellReuseId forIndexPath:indexPath]; + MWKImage *imageStub = self.uniqueArticleImages[indexPath.item]; MWKImageInfo *infoForImage = self.indexedImageInfo[imageStub.infoAssociationValue]; -- To view, visit https://gerrit.wikimedia.org/r/193292 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I24357d7f1636bda191e183489717cfcb8078839e Gerrit-PatchSet: 1 Gerrit-Project: apps/ios/wikipedia Gerrit-Branch: master Gerrit-Owner: Bgerstle <bgers...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits