Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into dismiss-presented
Browse files Browse the repository at this point in the history
# Conflicts:
#	Pod/Classes/ios/NYTPhotosViewController.m
  • Loading branch information
Mitch Livingston committed Feb 2, 2016
2 parents f7273da + 3cd27bd commit d2922c5
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 48 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

Changes for users of the library currently on `develop`:

- Fixes for incorrect logic determining whether to send delegate messages about `PhotosViewController` dismissal ([#130](https://github.com/NYTimes/NYTPhotoViewer/pull/130), TKTK)
_This space intentionally left blank._

## [1.0.1](https://github.com/NYTimes/NYTPhotoViewer/releases/tag/1.0.1)

Changes for users of the library in 1.0.1:

- Fixes for incorrect logic determining whether to send delegate messages about `PhotosViewController` dismissal ([#130](https://github.com/NYTimes/NYTPhotoViewer/pull/130), [#137](https://github.com/NYTimes/NYTPhotoViewer/pull/137))
- Avoid testing floats for equality in PhotoViewController ([#135](https://github.com/NYTimes/NYTPhotoViewer/pull/135))
- Fix orientation issue with reference view of type UIImageView ([#116](https://github.com/NYTimes/NYTPhotoViewer/pull/116), [#145](https://github.com/NYTimes/NYTPhotoViewer/pull/145))
- Avoid applying a hacky iOS status bar bugfix on iOS 8.3+ (it appears to have been fixed then) ([#131](https://github.com/NYTimes/NYTPhotoViewer/issues/131))
- Removed redundant Swift unit tests ([#128](https://github.com/NYTimes/NYTPhotoViewer/pull/128))

Expand Down
3 changes: 2 additions & 1 deletion Documentation/Release Process.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ _While tagging a new version of a library and pushing it to CocoaPods is concept
- When reviewing the commit history, searching for “Merge pull request” helps find changes which should appear in [the `CHANGELOG`](https://github.com/NYTimes/NYTPhotoViewer/blob/develop/CHANGELOG.md).
- Update any other documentation which still needs to be updated, given those changes.
- Create a pull request merging [`develop` into `master`](https://github.com/NYTimes/NYTPhotoViewer/compare/master...develop). Merge it yourself, immediately.
- Create a Github release, using the new version number (eg. `1.0.0`) as the tag, and the merge commit into `master` as the target. Copy [the `CHANGELOG`](https://raw.githubusercontent.com/NYTimes/NYTPhotoViewer/develop/CHANGELOG.md)’s Markdown content for this release into the Github release.
- Create a [Github release](https://github.com/NYTimes/NYTPhotoViewer/releases), using the new version number (eg. `1.0.0`) as the tag, and the merge commit into `master` as the target. Copy [the `CHANGELOG`](https://raw.githubusercontent.com/NYTimes/NYTPhotoViewer/develop/CHANGELOG.md)’s Markdown content for this release into the Github release.
- Push the new Podspec to Cocoapods Trunk: `pod trunk push NYTPhotoViewer.podspec`
- Ensure your local clone is up-to-date before this push.

## CocoaPods Trunk Setup

Expand Down
11 changes: 9 additions & 2 deletions Example/NYTPhotoViewer/NYTViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ - (void)updateImagesOnPhotosViewController:(NYTPhotosViewController *)photosView
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(updateImageDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (NYTExamplePhoto *photo in photos) {
if (!photo.image && !photo.imageData) {
// Photo credit: Nic Lehoux
photo.image = [UIImage imageNamed:@"NYTimesBuilding"];
[photosViewController updateImageForPhoto:photo];
}
Expand Down Expand Up @@ -99,7 +98,7 @@ + (NSArray *)newTestPhotos {

photo.attributedCaptionTitle = [[NSAttributedString alloc] initWithString:@(i + 1).stringValue attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody]}];
photo.attributedCaptionSummary = [[NSAttributedString alloc] initWithString:caption attributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor], NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody]}];
photo.attributedCaptionCredit = [[NSAttributedString alloc] initWithString:@"credit" attributes:@{NSForegroundColorAttributeName: [UIColor grayColor], NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]}];
photo.attributedCaptionCredit = [[NSAttributedString alloc] initWithString:@"NYT Building Photo Credit: Nic Lehoux" attributes:@{NSForegroundColorAttributeName: [UIColor grayColor], NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]}];

[photos addObject:photo];
}
Expand Down Expand Up @@ -156,6 +155,14 @@ - (NSDictionary *)photosViewController:(NYTPhotosViewController *)photosViewCont
return nil;
}

- (NSString *)photosViewController:(NYTPhotosViewController *)photosViewController titleForPhoto:(id<NYTPhoto>)photo atIndex:(NSUInteger)photoIndex totalPhotoCount:(NSUInteger)totalPhotoCount {
if ([photo isEqual:self.photos[NYTViewControllerPhotoIndexCustomEverything]]) {
return [NSString stringWithFormat:@"%lu/%lu", (unsigned long)photoIndex+1, (unsigned long)totalPhotoCount];
}

return nil;
}

- (void)photosViewController:(NYTPhotosViewController *)photosViewController didNavigateToPhoto:(id <NYTPhoto>)photo atIndex:(NSUInteger)photoIndex {
NSLog(@"Did Navigate To Photo: %@ identifier: %lu", photo, (unsigned long)photoIndex);
}
Expand Down
5 changes: 0 additions & 5 deletions Example/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,3 @@ end
target 'NYTPhotoViewer-Swift', :exclusive => true do
pod "NYTPhotoViewer/AnimatedGifSupport", :path => "../"
end

target 'NYTPhotoViewer-SwiftTests', :exclusive => true do
pod "NYTPhotoViewer/AnimatedGifSupport", :path => "../"
pod 'OCMock', '~> 3.2'
end
1 change: 0 additions & 1 deletion Example/Tests/NYTPhotosOverlayViewTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#import <NYTPhotoViewer/NYTPhotosOverlayView.h>

@interface NYTPhotosOverlayViewTests : XCTestCase

@end

@implementation NYTPhotosOverlayViewTests
Expand Down
78 changes: 74 additions & 4 deletions Example/Tests/NYTPhotosViewControllerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
@import UIKit;
@import XCTest;

#import <OCMock/OCMock.h>

#import <NYTPhotoViewer/NYTPhotosViewController.h>
#import "NYTExamplePhoto.h"

@interface NYTPhotosViewControllerTests : XCTestCase
@end

@interface NYTPhotosViewController (Testing)

- (void)dismissViewControllerAnimated:(BOOL)animated userInitiated:(BOOL)isUserInitiated completion:(void (^)(void))completion;
- (void)didPanWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer;
- (void)doneButtonTapped:(id)sender;

@end

Expand Down Expand Up @@ -127,22 +136,47 @@ - (void)testRightBarButtonItemsAreNilAfterSettingToNil {
XCTAssertNil(photosViewController.rightBarButtonItems);
}

- (void)testConvenienceInitializerAcceptsNil {
- (void)testOneArgConvenienceInitializerAcceptsNil {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:nil]);
}

- (void)testDesignatedInitializerAcceptsNilForPhotosParameter {
- (void)testTwoArgConvenienceInitializerAcceptsNilForPhotosParameter {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:nil initialPhoto:[[NYTExamplePhoto alloc] init]]);
}

- (void)testDesignatedInitializerAcceptsNilForInitialPhotoParameter {
- (void)testTwoArgConvenienceInitializerAcceptsNilForInitialPhotoParameter {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:[self newTestPhotos] initialPhoto:nil]);
}

- (void)testDesignatedInitializerAcceptsNilForBothParameters {
- (void)testTwoArgConvenienceInitializerAcceptsNilForBothParameters {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:nil initialPhoto:nil]);
}

- (void)testDesignatedInitializerAcceptsNilForPhotosParameter {
id delegateMock = OCMProtocolMock(@protocol(NYTPhotosViewControllerDelegate));
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:nil initialPhoto:[NYTExamplePhoto new] delegate:delegateMock]);
}

- (void)testDesignatedInitializerAcceptsNilForInitialPhotoParameter {
id delegateMock = OCMProtocolMock(@protocol(NYTPhotosViewControllerDelegate));
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:[self newTestPhotos] initialPhoto:nil delegate:delegateMock]);
}

- (void)testDesignatedInitializerAcceptsNilForDelegateParameter {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:[self newTestPhotos] initialPhoto:[NYTExamplePhoto new] delegate:nil]);
}

- (void)testDesignatedInitializerAcceptsNilForAllParameters {
XCTAssertNoThrow([[NYTPhotosViewController alloc] initWithPhotos:nil initialPhoto:nil delegate:nil]);
}

- (void)testDesignatedInitializerSetsDelegate {
id delegateMock = OCMProtocolMock(@protocol(NYTPhotosViewControllerDelegate));
NYTPhotosViewController *sut = [[NYTPhotosViewController alloc] initWithPhotos:[self newTestPhotos] initialPhoto:nil delegate:delegateMock];

XCTAssertEqual(sut.delegate, delegateMock);
}

- (void)testDisplayPhotoAcceptsNil {
NYTPhotosViewController *photosViewController = [[NYTPhotosViewController alloc] initWithPhotos:[self newTestPhotos]];
XCTAssertNoThrow([photosViewController displayPhoto:nil animated:NO]);
Expand Down Expand Up @@ -212,6 +246,42 @@ - (void)testPageViewIsntLoadedAfterInit {
XCTAssertFalse(photosViewController.pageViewController.isViewLoaded);
}

- (void)testDoneButtonDismissalUserInitiatedFlagIsTrue {
NSArray *photos = [self newTestPhotos];
NYTPhotosViewController *photosViewController = [[NYTPhotosViewController alloc] initWithPhotos:photos];

id photosVCMock = OCMPartialMock(photosViewController);

[photosViewController doneButtonTapped:nil];

OCMVerify([photosVCMock dismissViewControllerAnimated:YES userInitiated:YES completion:[OCMArg any]]);
}

- (void)testGestureBasedDismissalUserInitiatedFlagIsTrue {
NSArray *photos = [self newTestPhotos];
NYTPhotosViewController *photosViewController = [[NYTPhotosViewController alloc] initWithPhotos:photos];

id photosVCMock = OCMPartialMock(photosViewController);

id gestureRecognizerMock = OCMClassMock([UIPanGestureRecognizer class]);
OCMStub([gestureRecognizerMock state]).andReturn(UIGestureRecognizerStateBegan);

[photosViewController didPanWithGestureRecognizer:gestureRecognizerMock];

OCMVerify([photosVCMock dismissViewControllerAnimated:YES userInitiated:YES completion:[OCMArg any]]);
}

- (void)testProgrammaticDismissalUserInitiatedFlagIsFalse {
NSArray *photos = [self newTestPhotos];
NYTPhotosViewController *photosViewController = [[NYTPhotosViewController alloc] initWithPhotos:photos];

id photosVCMock = OCMPartialMock(photosViewController);

[photosViewController dismissViewControllerAnimated:YES completion:nil];

OCMVerify([photosVCMock dismissViewControllerAnimated:YES userInitiated:NO completion:[OCMArg any]]);
}

#pragma mark - Helpers

- (NSArray *)newTestPhotos {
Expand Down
2 changes: 1 addition & 1 deletion NYTPhotoViewer.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "NYTPhotoViewer"
s.version = "1.0.0"
s.version = "1.0.1"

s.description = <<-DESC
NYTPhotoViewer is a slideshow and image viewer that includes double tap to zoom, captions, support for multiple images, interactive flick to dismiss, animated zooming presentation, and more.
Expand Down
21 changes: 15 additions & 6 deletions Pod/Classes/ios/NYTPhotoTransitionAnimator.m
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,22 @@ + (UIView *)newAnimationViewFromView:(UIView *)view {
if (!view) {
return nil;
}

UIView *animationView;

if (view.layer.contents) {
animationView = [[UIView alloc] initWithFrame:view.frame];
animationView.layer.contents = view.layer.contents;
animationView.layer.bounds = view.layer.bounds;
if ([view isKindOfClass:[UIImageView class]]) {
// The case of UIImageView is handled separately since the mere layer's contents (i.e. CGImage in this case) doesn't
// seem to contain proper informations about the image orientation for portrait images taken directly on the device.
// See https://github.com/NYTimes/NYTPhotoViewer/issues/115
animationView = [(UIImageView *)[[view class] alloc] initWithImage:((UIImageView *)view).image];
animationView.bounds = view.bounds;
}
else {
animationView = [[UIView alloc] initWithFrame:view.frame];
animationView.layer.contents = view.layer.contents;
animationView.layer.bounds = view.layer.bounds;
}

animationView.layer.cornerRadius = view.layer.cornerRadius;
animationView.layer.masksToBounds = view.layer.masksToBounds;
animationView.contentMode = view.contentMode;
Expand All @@ -239,7 +248,7 @@ + (UIView *)newAnimationViewFromView:(UIView *)view {
else {
animationView = [view snapshotViewAfterScreenUpdates:YES];
}

return animationView;
}

Expand Down
5 changes: 3 additions & 2 deletions Pod/Classes/ios/NYTPhotoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ - (void)didDoubleTapWithGestureRecognizer:(UITapGestureRecognizer *)recognizer {
CGPoint pointInView = [recognizer locationInView:self.scalingImageView.imageView];

CGFloat newZoomScale = self.scalingImageView.maximumZoomScale;

if (self.scalingImageView.zoomScale >= self.scalingImageView.maximumZoomScale) {

if (self.scalingImageView.zoomScale >= self.scalingImageView.maximumZoomScale
|| ABS(self.scalingImageView.zoomScale - self.scalingImageView.maximumZoomScale) <= 0.01) {
newZoomScale = self.scalingImageView.minimumZoomScale;
}

Expand Down
52 changes: 47 additions & 5 deletions Pod/Classes/ios/NYTPhotosViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,25 @@

NS_ASSUME_NONNULL_BEGIN

// All notifications will have the `NYTPhotosViewController` instance set as the object.
/**
* Notification name issued when this `NYTPhotosViewController` navigates to a different photo.
*
* Includes the `NYTPhotosViewController` instance, as the notification's object.
*/
extern NSString * const NYTPhotosViewControllerDidNavigateToPhotoNotification;

/**
* Notification name issued when this `NYTPhotosViewController` is about to be dismissed.
*
* Includes the `NYTPhotosViewController` instance, as the notification's object.
*/
extern NSString * const NYTPhotosViewControllerWillDismissNotification;

/**
* Notification name issued when this `NYTPhotosViewController` has been dismissed.
*
* Includes the `NYTPhotosViewController` instance, as the notification's object.
*/
extern NSString * const NYTPhotosViewControllerDidDismissNotification;

@interface NYTPhotosViewController : UIViewController
Expand Down Expand Up @@ -73,23 +89,34 @@ extern NSString * const NYTPhotosViewControllerDidDismissNotification;
@property (nonatomic, weak, nullable) id <NYTPhotosViewControllerDelegate> delegate;

/**
* A convenience initializer that calls `initWithPhotos:initialPhoto:`, passing the first photo as the `initialPhoto` argument.
* A convenience initializer that calls `initWithPhotos:initialPhoto:delegate:`, passing the first photo as the `initialPhoto` argument, and `nil` as the `delegate` argument.
*
* @param photos An array of objects conforming to the `NYTPhoto` protocol.
*
* @return A fully initialized object.
*/
- (instancetype)initWithPhotos:(NSArray <id <NYTPhoto>> * _Nullable)photos;

/**
* A convenience initializer that calls `initWithPhotos:initialPhoto:delegate:`, passing `nil` as the `delegate` argument.
*
* @param photos An array of objects conforming to the `NYTPhoto` protocol.
* @param initialPhoto The photo to display initially. Must be contained within the `photos` array. If `nil` or not within the `photos` array, the first photo within the `photos` array will be displayed.
*
* @return A fully initialized object.
*/
- (instancetype)initWithPhotos:(NSArray <id <NYTPhoto>> * _Nullable)photos initialPhoto:(id <NYTPhoto> _Nullable)initialPhoto;

/**
* The designated initializer that stores the array of objects conforming to the `NYTPhoto` protocol for display, along with specifying an initial photo for display.
*
* @param photos An array of objects conforming to the `NYTPhoto` protocol.
* @param initialPhoto The photo to display initially. Must be contained within the `photos` array. If `nil` or not within the `photos` array, the first photo within the `photos` array will be displayed.
* @param delegate The delegate for this `NYTPhotosViewController`.
*
* @return A fully initialized object.
*/
- (instancetype)initWithPhotos:(NSArray <id <NYTPhoto>> * _Nullable)photos initialPhoto:(id <NYTPhoto> _Nullable)initialPhoto NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithPhotos:(NSArray <id <NYTPhoto>> * _Nullable)photos initialPhoto:(id <NYTPhoto> _Nullable)initialPhoto delegate:(nullable id <NYTPhotosViewControllerDelegate>)delegate NS_DESIGNATED_INITIALIZER;

/**
* Displays the specified photo. Can be called before the view controller is displayed. Calling with a photo not contained within the data source has no effect.
Expand Down Expand Up @@ -125,14 +152,15 @@ extern NSString * const NYTPhotosViewControllerDidDismissNotification;
- (void)photosViewController:(NYTPhotosViewController *)photosViewController didNavigateToPhoto:(id <NYTPhoto>)photo atIndex:(NSUInteger)photoIndex;

/**
* Called immediately before the photos view controller is about to start dismissal. This will be the beginning of the interactive panning to dismiss, if it is enabled and performed.
* Called immediately before the `NYTPhotosViewController` is about to start a user-initiated dismissal.
* This will be the beginning of the interactive panning to dismiss, if it is enabled and performed.
*
* @param photosViewController The `NYTPhotosViewController` instance that sent the delegate message.
*/
- (void)photosViewControllerWillDismiss:(NYTPhotosViewController *)photosViewController;

/**
* Called immediately after the photos view controller has dismissed.
* Called immediately after the photos view controller has been dismissed by the user.
*
* @param photosViewController The `NYTPhotosViewController` instance that sent the delegate message.
*/
Expand All @@ -148,6 +176,20 @@ extern NSString * const NYTPhotosViewControllerDidDismissNotification;
*/
- (UIView * _Nullable)photosViewController:(NYTPhotosViewController *)photosViewController captionViewForPhoto:(id <NYTPhoto>)photo;

/**
* Returns a string to display as the title in the navigation-bar area for a photo.
*
* This small area of the screen is not intended to display a caption or similar information about the photo itself. (NYTPhotoViewer is designed to provide this information in the caption view, and as such the `NYTPhoto` protocol provides properties for the title, summary, and credit for each photo.) Instead, consider using this delegate method to customize how your app displays the user's progress through a set of photos.
*
* @param photosViewController The `NYTPhotosViewController` instance that sent the delegate message.
* @param photo The photo object for which to display the title.
* @param photoIndex The index of the photo.
* @param totalPhotoCount The number of photos being displayed by the photo viewer.
*
* @return The text to display as the navigation-item title for the given photo. Return `nil` to show a default title like "1 of 4" indicating progress in a slideshow, or an empty string to hide this text entirely.
*/
- (NSString * _Nullable)photosViewController:(NYTPhotosViewController *)photosViewController titleForPhoto:(id <NYTPhoto>)photo atIndex:(NSUInteger)photoIndex totalPhotoCount:(NSUInteger)totalPhotoCount;

/**
* Returns a view to display while a photo is loading. Can be any `UIView` object, but is expected to respond to `sizeToFit` appropriately. This view will be sized and centered in the blank area, and hidden when the photo image is loaded.
*
Expand Down
Loading

0 comments on commit d2922c5

Please sign in to comment.