在swizzled类方法中设置的类类的属性总是返回nil

时间:2014-08-11 15:22:01

标签: ios objective-c uiimage objective-c-category swizzling

我想创建一个UIImage类的类,它将自己处理

(UIImage*) imageNamed:(NSString*) name

将为我保存名称作为创建图像属性的方法。为了做到这一点,我为这个方法创建了一个混合体,并为我的新添加的setter和getter属性创建了相关的引用。最后,实现看起来像这样:

@interface UIImage (MTReady)

@property(assign) NSString* imageName;

-(NSString*) getImageName;

@end

NSString * const imageNameKey = @"imageNameKey";

@implementation UIImage (MTReady)
@dynamic imageName;

-(NSString *)getImageName {
    NSString* name = objc_getAssociatedObject(self, &imageNameKey);
    return name;
}

-(void) setImageName:(NSString *)name {
    objc_setAssociatedObject(self, &imageNameKey, name, OBJC_ASSOCIATION_ASSIGN);
}

+(void)load {
    if(self == [UIImage class]) {
        Method originalImageNamed, swizzledImageNamed;

        originalImageNamed = class_getClassMethod(self, @selector(imageNamed:));
        swizzledImageNamed = class_getClassMethod(self, @selector(swizzledImageNamed:));
        method_exchangeImplementations(originalImageNamed, swizzledImageNamed);
    }
}

+(UIImage *)swizzledImageNamed:(NSString*) name {
    UIImage* image = [self swizzledImageNamed:name];

    if(image)
        [image setImageName:name];
    return image;
}

@end

这个解决方案似乎不起作用,因为每当我在使用方法 imageNamed 创建的UIImage上调用 getImageName 时,我总是得到 nil 。我目前没有想法为什么会这样。我的实施中是否缺少某些内容?

1 个答案:

答案 0 :(得分:0)

问题在于

  objc_setAssociatedObject(self, &imageNameKey, name, OBJC_ASSOCIATION_ASSIGN);

应该是

 objc_setAssociatedObject(self, &imageNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);

 objc_setAssociatedObject(self, &imageNameKey, name, OBJC_ASSOCIATION_COPY);

不要使用OBJC_ASSOCIATION_RETAINOBJC_ASSOCIATION_RETAIN_NONATOMIC,因为字符串可能是可变的。将字符串属性声明为copy而不是strong的完全相同的原因。

当我测试下面的代码时,正确设置和检索关联。

@implementation UIImage (Name)

static char const imageNameKey;

-(NSString *)getImageName {
  NSString* name = objc_getAssociatedObject(self, &imageNameKey);
  return name;
}

-(void) setImageName:(NSString *)name {
  objc_setAssociatedObject(self, &imageNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

+(void)load {
  if(self == [UIImage class]) {
    Method originalImageNamed, swizzledImageNamed;

    originalImageNamed = class_getClassMethod(self, @selector(imageNamed:));
    swizzledImageNamed = class_getClassMethod(self, @selector(swizzledImageNamed:));
    method_exchangeImplementations(originalImageNamed, swizzledImageNamed);
 }
}

+(UIImage *)swizzledImageNamed:(NSString*) name {
  UIImage* image = [self swizzledImageNamed:name];

  if(image)
    [image setImageName:name];
  return image;
}

@end