0

I have created a method already that returns a UIImage as follows:

- (UIImage *)circularOverlayMask
{
    // Constants
    CGRect rect = self.navigationController.view.bounds;
    CGFloat width = rect.size.width;
    CGFloat height = rect.size.height;

    CGFloat diameter = width-(kInnerEdgeInset*2);
    CGFloat radius = diameter/2;
    CGPoint center = CGPointMake(width/2, height/2);
    UIColor *fillColor = [UIColor colorWithWhite:0 alpha:0.5];

    // Create the image context
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);

    // Create the bezier paths
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:rect];
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(center.x-radius, center.y-radius, diameter, diameter)];

    [clipPath appendPath:maskPath];
    clipPath.usesEvenOddFillRule = YES;

    [clipPath addClip];
    [fillColor setFill];
    [clipPath fill];

    UIImage *_maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return _maskedImage;
}  

This works as expected and is currently in my View Controller code. I am trying to better refactor the code for the view controller and would like to move this to an appropriate subclass.

My initial thoughts were to subclass UIImage and return the image somehow. Another thought was to subclass UIImageView and within the init method call initWithImage then [self circularOverlayMask];. Another thought would be to simply subclass NSObject and add the method, then import where needed and call a public + method.

Question
What is the correct approach to refactoring this simple method into a relevant subclass?

StuartM
  • 6,743
  • 18
  • 84
  • 160

1 Answers1

2

Instead of subclass, I would write a category of UIImage with this method. So to use it you would have to import your category:

#import "UIImage+Masks.h"

And then you can just call it from UIImage:

[UIImage circularOverlayMaskForRect:]
Enrico Susatyo
  • 19,372
  • 18
  • 95
  • 156
  • The method would have to take the view bounds as a parameter, for example `circularOverlayMaskForRect:`. – Martin R Jan 19 '14 at 23:18
  • @MartinR That is correct, thanks. I was just whipping up a quick example. – Enrico Susatyo Jan 19 '14 at 23:37
  • Thanks both, I have completed the above but when I call `UIImage *maskImage = [UIImage circularOverlayMaskForRect:self.view.bounds];` I get an error no known class method for selector `circular...`? How should this be called. I have imported the header as normal – StuartM Jan 19 '14 at 23:53
  • @StuartM of course you should write the actual category class first ;) https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html – Enrico Susatyo Jan 20 '14 at 00:14
  • I have written the category already if that is what you mean. I didn't just try to import a category that didn't exist it wouldn't build would it ;) – StuartM Jan 20 '14 at 09:37
  • @StuartM Hmm, did you declare the method in the .h file of your category? – Enrico Susatyo Jan 20 '14 at 09:46
  • @EnricoSusatyo - I had to create the image first `UIImage *newImage = [UIImage new];` then call the method on that `[newImage circularOverLayMaskForRect:self.view];` is this correct? I thought with a category I could call it in the same way your answer suggests? – StuartM Jan 21 '14 at 10:24
  • @StuartM It depends, if you declared the method as an instance method (with a + sign instead of - sign), you can call it like my example. It's the same with all Obj-C classes, not only category. But I assume now you have successfully written this category? – Enrico Susatyo Jan 21 '14 at 10:49
  • *sorry, the one with the + sign is called class method, not instance method. – Enrico Susatyo Jan 21 '14 at 10:59
  • Yes thanks, I will update this to be a class method instead (+). I guess there is no issue here if this is a class/instance method – StuartM Jan 21 '14 at 13:32
  • @EnricoSusatyo - is there no issue here if this is a class/instance method? – StuartM Jan 22 '14 at 13:35
  • @StuartM In this particular case, I think it's ok. Read more here: http://stackoverflow.com/a/1053722/361247 – Enrico Susatyo Jan 22 '14 at 21:57