将全局 class 应用于 UIImage

Apply global class to UIImage

现在我不确定这在 Objective-C 中是否可行,但我希望它应该可行。

我使用 UIImages

上的 following/similar 代码在我的故事板上有多张图片
cell.followingImage.layer.cornerRadius = cell.followingImage.frame.size.width / 2;
cell.followingImage.clipsToBounds = YES;

我想优化代码。我知道您可以将 classes 应用于对象,但我以前从未这样做过。是否可以通过故事板应用 class 并自动 运行 该代码而不引用并将其添加到每个控制器?

因此,如果 class 附加到 UIImage,它只会 运行 该代码并使 UIImage 成为一个圆圈?这可能真的很简单...

如果我要子class 一个 UIimage 我不知道把上面的代码放在哪里?

尝试制作一个UIImage的类别。在此自定义类别 class 中包含您想要的所有内容,例如 cornerRadius 和 clipToBounds 代码。然后,当您初始化图像时,不要使用 [UIImage new] 而是使用 [customImageCategoryName new[.现在,默认情况下,所有这些图像都将包含这两行代码。以下link将向您展示如何在XcodeHow do I create a category in Xcode 6 or higher?

中创建类别

请将该代码放入 -(instancetype)initWithCoder:(NSCoder *)aDecoder 方法 , -(instancetype)initWithFrame:(CGRect)frame 方法 和 init 方法。

这样,如果 imageview 来自故事板,将调用 initWithCoder 并在以编程方式添加时调用其他方法。

由于 none 的其他答案确实有效但不够完整,所以我改用了 User Defined Runtime Attributes

为了避免在代码中编写它,我添加了

layer.cornerRadius Number 属性宽度的一半。

layer.masksToBounds Bool 属性为 YES

您的 "answer" 表明您在 Storyboard 中使用了 UIImageView。最好的方法是创建 UIImageView 的子 class,例如:

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

适配 cornerRadiusclipsToBounds 的代码应添加到 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.
}

编写该代码后,您需要将 Storyboard 中所有 UIImageView 的 class 属性(所有应该是循环的)设置为 MyImageView 而不是默认值UIImageView.

方法混合是实现这一目标的一个很好的选择。 创建一个 UIImageView 类别 class 并调整 initWithCoder: 方法

#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;
}

您不必创建 UIImageView 的子class,也不需要在 XIB/Storybord.

中的任何地方更改对象的 class

Click here 了解方法调配。