Although Jeff Lamarche's solution related to another answer works fine, it uses a lot of memory and / or does a lot of work:
- If you create
NSData once in the initializer, you end up holding a relatively large block of memory for the life of each button - If you do this transiently, as is done in the answer, then you end up converting the entire image every time you click the test on your button - process thousands of pixels and discard the result after receiving one byte!
It turns out you can do it much more efficiently, both in terms of memory usage and in terms of CPU consumption, following the approach described in this answer .
Subclass UIButton and override its pointInside:withEvent: method as follows:
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if (![super pointInside:point withEvent:event]) { return NO; } unsigned char pixel[1] = { 0 }; CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 1, NULL, (CGBitmapInfo)kCGImageAlphaOnly); UIGraphicsPushContext(context); UIImage *image = [self backgroundImageForState:UIControlStateNormal] ; [image drawAtPoint:CGPointMake(-point.x, -point.y)]; UIGraphicsPopContext(); CGContextRelease(context); return pixel[0] != 0; }
The above code accepts alpha from the button background image. If your button uses a different image, change the line that initializes the image variable above.
source share