public
Last active

iOS - UIButton+Block

  • Download Gist
UIButton+Block.h
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
//
// 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
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
//
// 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();
}
UIButtonBlock.h
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
//
// 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
UIButtonBlock.m
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
//
// 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();
}
ViewController.m
Objective-C
1 2 3 4 5 6 7 8
...
 
[button setAction:kUIButtonBlockTouchUpInside withBlock:^{
NSString* launchUrl = @"http://joshholtz.com";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: launchUrl]];
}];
 
..

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

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.

Code is updated now to copy the block.

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.

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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.