Skip to content

Instantly share code, notes, and snippets.

@lukeredpath
Created August 14, 2013 08:56
Show Gist options
  • Save lukeredpath/6229171 to your computer and use it in GitHub Desktop.
Save lukeredpath/6229171 to your computer and use it in GitHub Desktop.
I wanted a block-based API for UIAlertView on my current project, but didn't want to import a whole Pod/library just for that, so I wrote a quick and simple implementation myself. Licensed under the WTFPL license. (http://www.wtfpl.net).
//
// UIAlertView+BlockSupport.h
//
// Created by Luke Redpath on 08/08/2013.
//
#import <UIKit/UIKit.h>
/* Called when the user taps a button in the alert view or the alert
* is cancelled.
*
* If the alert was cancelled, wasCancelled will be YES and tappedButtonIndex
* will return the value of [UIAlertView cancelButtonIndex].
*/
typedef void (^LRAlertViewCompletionHandler)(UIAlertView *alertView, NSInteger tappedButtonIndex, BOOL wasCancelled);
@interface UIAlertView (BlockSupport)
- (void)showWithCompletionHandler:(LRAlertViewCompletionHandler)completionHandler;
@end
//
// UIAlertView+BlockSupport.m
//
// Created by Luke Redpath on 08/08/2013.
// Copyright (c) 2013 Luke Redpath. All rights reserved.
//
#import "UIAlertView+BlockSupport.h"
#import <objc/runtime.h>
@interface LRAlertViewBlockDelegate : NSObject <UIAlertViewDelegate>
- (id)initWithAlertView:(UIAlertView *)alertView;
- (void)showWithCompletionHandler:(LRAlertViewCompletionHandler)completionHandler;
@end
#pragma mark -
@implementation UIAlertView (BlockSupport)
- (void)showWithCompletionHandler:(LRAlertViewCompletionHandler)completionHandler
{
NSParameterAssert(completionHandler);
CNAlertViewBlockDelegate *blockDelegate = [[LRAlertViewBlockDelegate alloc] initWithAlertView:self];
[blockDelegate showWithCompletionHandler:completionHandler];
}
@end
#pragma mark -
@implementation LRAlertViewBlockDelegate {
UIAlertView *_alertView;
LRAlertViewCompletionHandler _completionHandler;
}
#define kLRAlertViewBlockDelegateRefKey "LRAlertViewBlockDelegate"
- (id)initWithAlertView:(UIAlertView *)alertView
{
if ((self = [super init])) {
_alertView = alertView;
_alertView.delegate = self;
}
return self;
}
- (void)showWithCompletionHandler:(LRAlertViewCompletionHandler)completionHandler
{
_completionHandler = [completionHandler copy];
/* We need to keep a strong reference to self or it will just be deallocated immediately.
*
* This technically creates a retain cycle between the alert view and self which is OK,
* as we will make sure we break this retain cycle manually when the alert view is dismissed.
*/
objc_setAssociatedObject(_alertView, kLRAlertViewBlockDelegateRefKey, self, OBJC_ASSOCIATION_RETAIN);
[_alertView show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
_completionHandler(alertView, buttonIndex, NO);
}
- (void)alertViewCancel:(UIAlertView *)alertView
{
_completionHandler(alertView, alertView.cancelButtonIndex, YES);
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
/* The alert view will be deallocced shortly after this is called if nothing else is retaining
* it, so now's a good time to break the retain cycle.
*/
objc_setAssociatedObject(_alertView, kLRAlertViewBlockDelegateRefKey, nil, OBJC_ASSOCIATION_RETAIN);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment