Skip to content

Instantly share code, notes, and snippets.

@joshdholtz
Created April 23, 2012 04:37
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save joshdholtz/2468899 to your computer and use it in GitHub Desktop.
Save joshdholtz/2468899 to your computer and use it in GitHub Desktop.
iOS - UIButton+Block
//
// UIButton+Block.h
// BoothTag
//
// Created by Josh Holtz on 4/22/12.
// Copyright (c) 2012 Josh Holtz. All rights reserved.
//
#define kUIButtonBlockTouchUpInside @"TouchInside"
#import <UIKit/UIKit.h>
@interface UIButton (Block)
@property (nonatomic, strong) NSMutableDictionary *actions;
- (void) setAction:(NSString*)action withBlock:(void(^)())block;
@end
//
// UIButton+Block.m
// BoothTag
//
// Created by Josh Holtz on 4/22/12.
// Copyright (c) 2012 Josh Holtz. All rights reserved.
//
#import "UIButton+Block.h"
#import "/usr/include/objc/runtime.h"
@implementation UIButton (Block)
static char overviewKey;
@dynamic actions;
- (void) setAction:(NSString*)action withBlock:(void(^)())block {
if ([self actions] == nil) {
[self setActions:[[NSMutableDictionary alloc] init]];
}
[[self actions] setObject:block forKey:action];
if ([kUIButtonBlockTouchUpInside isEqualToString:action]) {
[self addTarget:self action:@selector(doTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)setActions:(NSMutableDictionary*)actions {
objc_setAssociatedObject (self, &overviewKey,actions,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableDictionary*)actions {
return objc_getAssociatedObject(self, &overviewKey);
}
- (void)doTouchUpInside:(id)sender {
void(^block)();
block = [[self actions] objectForKey:kUIButtonBlockTouchUpInside];
block();
}
//
// UIButton+Block.h
// BoothTag
//
// Created by Josh Holtz on 4/22/12.
// Copyright (c) 2012 Josh Holtz. All rights reserved.
//
#define kUIButtonBlockTouchUpInside @"TouchInside"
#import <UIKit/UIKit.h>
@interface UIButton (Block)
@property (nonatomic, strong) NSMutableDictionary *actions;
- (void) setAction:(NSString*)action withBlock:(void(^)())block;
@end
//
// UIButton+Block.m
// BoothTag
//
// Created by Josh Holtz on 4/22/12.
// Copyright (c) 2012 Josh Holtz. All rights reserved.
//
#import "UIButton+Block.h"
#import "/usr/include/objc/runtime.h"
@implementation UIButton (Block)
static char overviewKey;
@dynamic actions;
- (void) setAction:(NSString*)action withBlock:(void(^)())block {
if ([self actions] == nil) {
[self setActions:[[NSMutableDictionary alloc] init]];
}
[[self actions] setObject:[block copy] forKey:action];
if ([kUIButtonBlockTouchUpInside isEqualToString:action]) {
[self addTarget:self action:@selector(doTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)setActions:(NSMutableDictionary*)actions {
objc_setAssociatedObject (self, &overviewKey,actions,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableDictionary*)actions {
return objc_getAssociatedObject(self, &overviewKey);
}
- (void)doTouchUpInside:(id)sender {
void(^block)();
block = [[self actions] objectForKey:kUIButtonBlockTouchUpInside];
block();
}
...
[button setAction:kUIButtonBlockTouchUpInside withBlock:^{
NSString* launchUrl = @"http://joshholtz.com";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: launchUrl]];
}];
..
@rcomblen
Copy link

You need to copy the block to avoid the block to be garbage collected, see http://stackoverflow.com/questions/8852107/arc-related-crash-in-ios-when-using-a-block-pointer-as-a-member-variable

updated version at git://gist.github.com/2835270.git

@joshdholtz
Copy link
Author

Thanks combien! I actually did run across the issue and solved it with copying the block I just forgot to update my gist.

Thanks for the reminder though! Much appreciated.

@joshdholtz
Copy link
Author

Code is updated now to copy the block.

@tacke758
Copy link

tacke758 commented Nov 2, 2013

I love this simple extension.
It's better to change the import path #import "/usr/include/objc/runtime.h" into #import <objc/runtime.h> in order to prevent build failure in Xcode5.

@adamgit
Copy link

adamgit commented Nov 2, 2013

You only updated ONE of the missing "block copy" statemetns above. The UIButton+Block.m is broken.

@danielpetroianu
Copy link

Wouldn't it cause a retain cycle if you use self in the block implementation ?

@implementation ViewController
    //...
    [[self button] addAcction:kUIButtonBlockTouchUpInside  withBlock:^{
        [self doSomething];
    }]
    //...
@end

I'm asking because I'm trying to do something like this, and hate for the consumer of the control to always do :

__weak __typeof(self) weakSelf = self;
[[self button] addAcction:kUIButtonBlockTouchUpInside  withBlock:^{
    [weakSelf doSomething];
}]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment