【问题标题】:Apply global class to UIImage将全局类应用于 UIImage
【发布时间】:2015-03-24 14:34:44
【问题描述】:

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

我的故事板上有多个图像,使用 UIImages 上的以下/类似代码

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

我想优化代码。我知道您可以将类应用于对象,但我以前从未这样做过。是否可以通过情节提要应用该类并自动运行该代码而无需引用并将其添加到每个控制器?

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

如果我要对 UIimage 进行子类化,我不确定将上述代码放在哪里?

【问题讨论】:

  • 创建UIImage的子类,添加这段代码,然后将storyboard中的UIImage类改成你自定义的UIImage子类。
  • 嗨@LordZsolt。当我创建 UIImage 的子类时,代码在哪里?我是否在子类中创建 init 方法?

标签: ios uiimage


【解决方案1】:

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

【讨论】:

  • 我使用的是故事板
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    由于其他答案都没有真正奏效,也不够完整,我改用User Defined Runtime Attributes。

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

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

    layer.masksToBounds Bool 属性为YES

    【讨论】:

    • 这与将类应用于UIImage 有何关系?您正在修改 UIImageView,而不是 UIImage 本身。
    • 看看我的回答。您可以在一个地方简单地完成它而无需更改任何内容。
    【解决方案4】:

    方法调配是实现这一目标的一个很好的选择。 创建一个 UIImageView 类别类和 swizzle 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 的子类,也无需在 XIB/Storybord 中的任何地方更改对象的类。

    Click here 了解方法调配。

    【讨论】:

    • 简直恶心!在不了解 swizzling 的情况下,它消除了理解您在另一个类中编写的代码的任何可能性。如果你只是移动函数调用,如果你只看一个类的代码,你根本不知道调用了什么方法。不要这样做!
    • lik2302 - 方法混用有什么问题?
    【解决方案5】:

    您的“答案”表明您在情节提要中使用了UIImageViews。最好的方法是创建UIImageView 的子类,例如:

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

    适应cornerRadius和clipsToBounds的代码应该添加到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.
    }
    

    编写该代码后,您需要将情节提要中所有UIImageViews(所有应该是循环的)的类属性设置为MyImageView,而不是默认的UIImageView。

    【讨论】:

      猜你喜欢
      • 2018-01-28
      • 1970-01-01
      • 2013-11-17
      • 2014-07-14
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      相关资源
      最近更新 更多