2

Now I'm not sure if this is possible in Objective-C but I would expect it should be.

I have multiple images across my storyboard using the following/similar code on UIImages

cell.followingImage.layer.cornerRadius = cell.followingImage.frame.size.width / 2;
cell.followingImage.clipsToBounds = YES;

I want to optimise the code. I know you can apply classes to objects but I have never done this before. Is it possible to apply the class via the storyboard and automatically run that code without referencing and adding it to every controller?

So if a class is attached to the UIImage it would just run that code and make the UIImage a circle? This is probably really simple...

If I was to subclass a UIimage I'm not sure where to put the above code?

Allreadyhome
  • 1,252
  • 2
  • 25
  • 46
  • Create a subclass of `UIImage`, add this code into it, then change the class of the UIImage in the storyboard to your custom UIImage subclass. – Lord Zsolt Mar 24 '15 at 14:37
  • Hi @LordZsolt . When I create a subclass of UIImage where does the code go? Do I create a init method within the subclass? – Allreadyhome Mar 24 '15 at 17:35

5 Answers5

0

Try making a category of UIImage. Include everything you want in this custom category class like your cornerRadius and your clipToBounds code. Then when you init the images, don't init the images with [UIImage new] but with [customImageCategoryName new[. Now, all these images will, by default, have those two lines of code. The following link will show you how to create a category in Xcode How do I create a category in Xcode 6 or higher?

Community
  • 1
  • 1
0

Do place that code in -(instancetype)initWithCoder:(NSCoder *)aDecoder method , -(instancetype)initWithFrame:(CGRect)frame method and init method.

That way if the imageview is from storyboard the initWithCoder will get called and other methods get called when it is programatically added.

Abhi
  • 593
  • 4
  • 8
0

As none of the other answers really worked nor were complete enough I used User Defined Runtime Attributes instead.

To avoid the need to write it in code I added

layer.cornerRadius with Number attribute half the width.

layer.masksToBounds with Bool attribute as YES

Allreadyhome
  • 1,252
  • 2
  • 25
  • 46
-1

Method swizzling is a very good option to achieve this. Create a UIImageView category class and swizzle initWithCoder: method

#import "UIImageView+MethodSwizzling.h"
#import <objc/runtime.h>


@implementation UIImageView (MethodSwizzling)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(initWithCoder:);
        SEL swizzledSelector = @selector(xxx_initWithCoder:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(class, originalSelector);
        // Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        }
        else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling

- (id)xxx_initWithCoder:(NSCoder*)aDecoder {
    [self xxx_initWithCoder:aDecoder];
    self.layer.cornerRadius = self.frame.size.width / 2;
    self.layer.masksToBounds = YES;
    NSLog(@"xxx_initWithCoder: %@", self);
    return self;
}

You don't have to create subclass of UIImageView and do not need to change your object's class everywhere in XIB/Storybord.

Click here to know about method swizzling.

Rajender Kumar
  • 1,377
  • 19
  • 32
  • It is just disgusting! Without knowing much about swizzling it removes any possibility to understand the code you write in another class. If you just move function calls around you have no idea what method gets called if you just look at the code of one class. DONT do it! – luk2302 Apr 01 '15 at 18:27
  • lik2302 - What is the problem with method swizzling? – Rajender Kumar Apr 02 '15 at 05:02
-2

What your "answer" suggests is that you are using UIImageViews in the Storyboard. The best approach would be to create a subclass of UIImageView, e.g.:

//MyImageView.h
#import <UIKit/UIKit.h>
@interface MyImageView : UIImageView
@end

The code to adapt the cornerRadius and the clipsToBounds should be added to the MyImageView.m:

//MyImageView.m
- (id)layoutSubviews {
    [super layoutSubviews];
    self.layer.cornerRadius = self.view.frame.width.width / 2
    self.layer.clipsToBounds = true;
    // this line may be only needed in init since the clipsToBounds does not change due to autoLayout.
}

After writing that code, you need to set the class attribute of all UIImageViews in the Storyboard (all those that should be circular) to MyImageView instead of the default UIImageView.

luk2302
  • 55,258
  • 23
  • 97
  • 137