Skip to content

Instantly share code, notes, and snippets.

@mbbischoff
Created September 2, 2014 13:52
Show Gist options
  • Save mbbischoff/50c9e0fa06a4795a3812 to your computer and use it in GitHub Desktop.
Save mbbischoff/50c9e0fa06a4795a3812 to your computer and use it in GitHub Desktop.
//
// LCKAlertPresenter.h
// Quotebook
//
// Created by Matthew Bischoff on 9/1/14.
// Copyright (c) 2014 Lickability. All rights reserved.
//
@import Foundation;
@protocol LCKActionSheetPopoverPresenting <NSObject>
@property (nonatomic) UIView *sourceView;
@property (nonatomic) CGRect sourceRect;
@property (nonatomic) UIBarButtonItem *barButtonItem;
@end
@protocol LCKActionSheetActing <NSObject>
+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(id <LCKActionSheetActing> action))handler;
@property (nonatomic, copy) void (^handler)(id <LCKActionSheetActing> action);
@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) UIAlertActionStyle style;
@end
@interface LCKActionSheetAction : NSObject <LCKActionSheetActing>
@end
/**
* LCKActionSheetPresenter is a facade for UIActionSheet and UIAlertController that adapts depending on availability.
*/
@interface LCKActionSheetPresenter : NSObject
+ (instancetype)alertPresenterWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle;
- (void)addAction:(LCKActionSheetAction *)action;
- (void)presentInViewController:(UIViewController *)viewController view:(UIView *)view animated:(BOOL)animated;
@property (nonatomic, readonly) NSArray *actions;
@property (nonatomic, copy) NSString *title;
/// LCKActionSheetPopoverPresenter or UIPopoverPresentationController
@property (nonatomic, readonly) id <LCKActionSheetPopoverPresenting> popoverPresentationController;
@end
//
// LCKAlertPresenter.m
// Quotebook
//
// Created by Matthew Bischoff on 9/1/14.
// Copyright (c) 2014 Lickability. All rights reserved.
//
#import "LCKActionSheetPresenter.h"
#import "LCKAlertController.h"
#import "LCKActionSheet.h"
@interface LCKActionSheetPopoverPresenter : NSObject <LCKActionSheetPopoverPresenting>
@end
@implementation LCKActionSheetPopoverPresenter
@synthesize sourceView = _sourceView;
@synthesize sourceRect = _sourceRect;
@synthesize barButtonItem = _barButtonItem;
@end
@interface LCKActionSheetAction ()
@property (nonatomic, readwrite) NSString *title;
@property (nonatomic) UIAlertActionStyle style;
@end
@implementation LCKActionSheetAction
@synthesize handler = _handler;
@synthesize title = _title;
@synthesize style = _style;
+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(id <LCKActionSheetActing> action))handler {
LCKActionSheetAction *action = [[LCKActionSheetAction alloc] init];
action.title = title;
action.style = style;
action.handler = [handler copy];
return action;
}
- (UIAlertAction *)UIAlertAction {
return [UIAlertAction actionWithTitle:self.title style:self.style handler:(void(^)(UIAlertAction *))self.handler];
}
@end
@interface LCKActionSheetPresenter () <UIActionSheetDelegate>
@property (nonatomic) NSArray *actions;
@property (nonatomic) UIAlertController *alertController;
@property (nonatomic) id <LCKActionSheetPopoverPresenting> popoverPresentationController;
@end
@implementation LCKActionSheetPresenter
+ (instancetype)alertPresenterWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle {
return [[LCKActionSheetPresenter alloc] initWithTitle:title message:nil preferredStyle:preferredStyle];
}
- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle {
self = [super init];
if (self) {
_title = [title copy];
_actions = @[];
if ([UIAlertController class]) {
_alertController = [LCKAlertController alertControllerWithTitle:self.title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
}
}
return self;
}
- (void)addAction:(LCKActionSheetAction *)action {
if (action) {
self.actions = [self.actions arrayByAddingObjectsFromArray:@[action]];
}
if ([UIAlertAction class]) {
[self.alertController addAction:[action UIAlertAction]];
}
}
- (UIActionSheet *)newActionSheet {
LCKActionSheet *actionSheet = [[LCKActionSheet alloc] initWithTitle:self.title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
__block NSInteger cancelIndex = -1;
__block NSInteger destructiveIndex = NSNotFound;
__block LCKActionSheetAction *cancelAction;
[self.actions enumerateObjectsUsingBlock:^(LCKActionSheetAction *action, NSUInteger actionIndex, BOOL *stop) {
if (action.style == UIAlertActionStyleCancel) {
cancelAction = action;
cancelIndex = actionIndex;
}
else {
[actionSheet addButtonWithTitle:action.title];
}
if (action.style == UIAlertActionStyleDestructive) {
destructiveIndex = actionIndex;
}
}];
if (cancelAction) {
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:cancelAction.title];
}
actionSheet.destructiveButtonIndex = destructiveIndex;
return actionSheet;
}
- (void)presentInViewController:(UIViewController *)viewController view:(UIView *)view animated:(BOOL)animated {
if ([UIAlertController class]) {
[viewController presentViewController:self.alertController animated:animated completion:nil];
}
else {
UIActionSheet *actionSheet = [self newActionSheet];
if (self.popoverPresentationController.barButtonItem) {
[actionSheet showFromBarButtonItem:self.popoverPresentationController.barButtonItem animated:animated];
}
else if (self.popoverPresentationController.sourceView) {
[actionSheet showFromRect:self.popoverPresentationController.sourceRect inView:self.popoverPresentationController.sourceView animated:animated];
}
else {
[actionSheet showInView:view];
}
}
}
- (NSArray *)actionsAsUIAlertActions {
NSMutableArray *UIAlertActions = [NSMutableArray array];
for (LCKActionSheetAction *action in self.actions) {
[UIAlertActions addObject:[action UIAlertAction]];
}
return UIAlertActions;
}
- (id)popoverPresentationController {
if ([self.alertController respondsToSelector:@selector(popoverPresentationController)]) {
return self.alertController.popoverPresentationController;
}
else if (!_popoverPresentationController) {
_popoverPresentationController = [[LCKActionSheetPopoverPresenter alloc] init];
}
return _popoverPresentationController;
}
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
actionSheet.delegate = nil;
NSMutableArray *correctedActions = [self.actions mutableCopy];
LCKActionSheetAction *cancelAction;
for (LCKActionSheetAction *action in self.actions) {
if (action.style == UIAlertActionStyleCancel) {
cancelAction = action;
}
}
if (cancelAction) {
[correctedActions removeObject:cancelAction];
[correctedActions addObject:cancelAction];
}
LCKActionSheetAction *action = correctedActions[buttonIndex];
if (action.handler) {
action.handler(action);
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
actionSheet.delegate = nil;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment