Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
@import UIKit;
NS_ASSUME_NONNULL_BEGIN
@protocol MFBPreviewableCollectionView
- (nullable NSIndexPath *)mfb_previewableCollectionIndexPathForItemAtPoint:(CGPoint)point;
- (CGRect)mfb_previewableCollectionItemRectForIndexPath:(NSIndexPath *)indexPath;
@end
@class MFBCollectionPreviewingAdapter;
@protocol MFBPreviewableStateHolder <NSObject>
- (nullable id)previewingAdapter:(MFBCollectionPreviewingAdapter *)adapter modelObjectForViewIndexPath:(NSIndexPath *)indexPath;
@end
@protocol MFBCollectionPreviewingViewFactory <NSObject>
- (UIViewController *)previewingAdapter:(MFBCollectionPreviewingAdapter *)adapter viewControllerForPreviewingModelObject:(id)modelObject;
@end
@protocol MFBCollectionPreviewingCommitter <NSObject>
- (void)previewingAdapter:(MFBCollectionPreviewingAdapter *)adapter commitViewController:(UIViewController *)viewController;
@end
@interface MFBCollectionPreviewingAdapter : NSObject <UIViewControllerPreviewingDelegate>
@property (nonatomic, weak) IBOutlet id<MFBPreviewableStateHolder> stateHolder;
@property (nonatomic, weak) IBOutlet id<MFBCollectionPreviewingViewFactory> viewFactory;
@property (nonatomic, weak) IBOutlet id<MFBCollectionPreviewingCommitter> committer;
- (void)registerViewController:(UIViewController *)viewController forPreviewingWithSourceView:(id<MFBPreviewableCollectionView>)sourceView;
@end
@interface UITableView (MFBPreviewableCollectionView) <MFBPreviewableCollectionView>
@end
NS_ASSUME_NONNULL_END
#import "MFBCollectionPreviewingAdapter.h"
NS_ASSUME_NONNULL_BEGIN
@implementation UITableView (MFBPreviewableCollectionView)
- (nullable NSIndexPath *)mfb_previewableCollectionIndexPathForItemAtPoint:(CGPoint)point
{
return [self indexPathForRowAtPoint:point];
}
- (CGRect)mfb_previewableCollectionItemRectForIndexPath:(NSIndexPath *)indexPath
{
return [self rectForRowAtIndexPath:indexPath];
}
@end
@implementation MFBCollectionPreviewingAdapter {
__weak id<MFBPreviewableCollectionView> _sourceView;
}
- (void)registerViewController:(UIViewController *)viewController forPreviewingWithSourceView:(id)sourceView
{
if (![viewController respondsToSelector:@selector(registerForPreviewingWithDelegate:sourceView:)]) {
return;
}
[viewController registerForPreviewingWithDelegate:self sourceView:sourceView];
_sourceView = sourceView;
}
- (nullable UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
NSIndexPath *indexPath = [_sourceView mfb_previewableCollectionIndexPathForItemAtPoint:location];
if (!indexPath) {
return nil;
}
id modelObject = [_stateHolder previewingAdapter:self modelObjectForViewIndexPath:indexPath];
if (!modelObject) {
return nil;
}
CGRect itemRect = [_sourceView mfb_previewableCollectionItemRectForIndexPath:indexPath];
if (!CGRectEqualToRect(CGRectZero, itemRect)) {
previewingContext.sourceRect = itemRect;
}
return [_viewFactory previewingAdapter:self viewControllerForPreviewingModelObject:modelObject];
}
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
{
[_committer previewingAdapter:self commitViewController:viewControllerToCommit];
}
@end
@import XCTest;
#import <OCMock/OCMock.h>
#import "MFBCollectionPreviewingAdapter.h"
@interface MFBCollectionPreviewingAdapterTests : XCTestCase
@end
@implementation MFBCollectionPreviewingAdapterTests {
id _sourceViewMock;
id _viewFactoryMock;
id _committerMock;
id _stateHolderMock;
id _previewableViewControllerMock;
MFBCollectionPreviewingAdapter *_adadpter;
CGPoint _point;
NSIndexPath *_indexPath;
id _modelStub;
}
- (void)setUp
{
[super setUp];
_sourceViewMock = OCMProtocolMock(@protocol(MFBPreviewableCollectionView));
_viewFactoryMock = OCMProtocolMock(@protocol(MFBCollectionPreviewingViewFactory));
_committerMock = OCMProtocolMock(@protocol(MFBCollectionPreviewingCommitter));
_stateHolderMock = OCMProtocolMock(@protocol(MFBPreviewableStateHolder));
_adadpter = [MFBCollectionPreviewingAdapter new];
_previewableViewControllerMock = OCMClassMock([UIViewController class]);
[_adadpter registerViewController:_previewableViewControllerMock forPreviewingWithSourceView:_sourceViewMock];
_adadpter.viewFactory = _viewFactoryMock;
_adadpter.committer = _committerMock;
_adadpter.stateHolder = _stateHolderMock;
_point = CGPointMake(arc4random(), arc4random());
_indexPath = [NSIndexPath indexPathForRow:(NSInteger) arc4random() inSection:0];
_modelStub = [NSObject new];
}
- (void)test_RegisterViewController_CallsProperViewControllerMethod
{
OCMVerify([_previewableViewControllerMock registerForPreviewingWithDelegate:_adadpter sourceView:_sourceViewMock]);
}
- (void)test_RegisterViewController_DoesNotRetainSourceView
{
NS_VALID_UNTIL_END_OF_SCOPE MFBCollectionPreviewingAdapter *adapter = [MFBCollectionPreviewingAdapter new];
id sourceViewStub = [NSObject new];
__weak id sourceViewStubWeak = sourceViewStub;
[adapter registerViewController:_previewableViewControllerMock forPreviewingWithSourceView:sourceViewStub];
sourceViewStub = nil;
XCTAssertNil(sourceViewStubWeak);
}
- (void)test_ViewControllerForLocation_NoIndexPath
{
OCMExpect([_sourceViewMock mfb_previewableCollectionIndexPathForItemAtPoint:_point]).andReturn(nil);
id viewController = [_adadpter previewingContext:(id) [NSObject new] viewControllerForLocation:_point];
OCMVerifyAll(_sourceViewMock);
XCTAssertNil(viewController);
}
- (void)test_ViewControllerForLocation_NoModelObject
{
OCMStub([_sourceViewMock mfb_previewableCollectionIndexPathForItemAtPoint:_point]).andReturn(_indexPath);
OCMExpect([_stateHolderMock previewingAdapter:_adadpter modelObjectForViewIndexPath:_indexPath]).andReturn(nil);
id viewController = [_adadpter previewingContext:(id) [NSObject new] viewControllerForLocation:_point];
OCMVerifyAll(_stateHolderMock);
XCTAssertNil(viewController);
}
- (void)test_ViewControllerForLocation_ItemRectNotZero_AssignsItemRectToContext
{
id previewingContextMock = OCMProtocolMock(@protocol(UIViewControllerPreviewing));
CGRect itemRect = CGRectMake(10, 200, 500, 320);
OCMStub([_sourceViewMock mfb_previewableCollectionIndexPathForItemAtPoint:_point]).andReturn(_indexPath);
OCMStub([_stateHolderMock previewingAdapter:_adadpter modelObjectForViewIndexPath:_indexPath]).andReturn(_modelStub);
OCMStub([_sourceViewMock mfb_previewableCollectionItemRectForIndexPath:_indexPath]).andReturn(itemRect);
__unused id viewController = [_adadpter previewingContext:previewingContextMock viewControllerForLocation:_point];
OCMVerify([previewingContextMock setSourceRect:itemRect]);
}
- (void)test_ViewControllerForLocation_ItemRectZero_DoesNotAssignItemRectToContext
{
id previewingContextMock = OCMProtocolMock(@protocol(UIViewControllerPreviewing));
CGRect itemRect = CGRectZero;
OCMStub([_sourceViewMock mfb_previewableCollectionIndexPathForItemAtPoint:_point]).andReturn(_indexPath);
OCMStub([_stateHolderMock previewingAdapter:_adadpter modelObjectForViewIndexPath:_indexPath]).andReturn(_modelStub);
OCMStub([_sourceViewMock mfb_previewableCollectionItemRectForIndexPath:_indexPath]).andReturn(itemRect);
[[[previewingContextMock reject] ignoringNonObjectArgs] setSourceRect:CGRectNull];
__unused id viewController = [_adadpter previewingContext:previewingContextMock viewControllerForLocation:_point];
}
- (void)test_ViewControllerForLocation_AsksFactoryToBuildVC
{
id expectedViewController = [NSObject new];
OCMStub([_sourceViewMock mfb_previewableCollectionIndexPathForItemAtPoint:_point]).andReturn(_indexPath);
OCMStub([_stateHolderMock previewingAdapter:_adadpter modelObjectForViewIndexPath:_indexPath]).andReturn(_modelStub);
OCMStub([_viewFactoryMock previewingAdapter:_adadpter viewControllerForPreviewingModelObject:_modelStub]).andReturn(expectedViewController);
id viewController = [_adadpter previewingContext:OCMProtocolMock(@protocol(UIViewControllerPreviewing)) viewControllerForLocation:_point];
XCTAssertEqual(viewController, expectedViewController);
}
- (void)test_CommitViewController_ForwardsToCommitter
{
id expectedViewController = [NSObject new];
[_adadpter previewingContext:(id) [NSObject new] commitViewController:expectedViewController];
OCMVerify([_committerMock previewingAdapter:_adadpter commitViewController:expectedViewController]);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment