IOS下Category添加属性字段

作者: zuolingfeng | 来源:发表于2015-08-12 15:19 被阅读7846次

首先说明一下,直接在Category中是不能添加属性的,就算在.m文件中实现了相应的getter和setter方法,调用的时候也是会报错的。

首先看下报错情况

Category添加字段(常规方法)

1, 编写Category头文件,以UIImage为例


//
//  UIImage+category.h
//  
//
//  Created by Linf on 15-5-19.
//  Copyright (c) 2015年 Linf. All rights reserved.
//
#import <UIKit/UIKit.h>

@interface UIImage (category)

// 在UIImage中新建一个tag属性
@property (nonatomic, copy) NSString *tag;

@end

2,编写Category源文件

//
//  UIImage+category.m
//  
//
//  Created by Linf on 15-5-19.
//  Copyright (c) 2015年 Linf. All rights reserved.
//

#import "UIImage+category.h"

@implementation UIImage (category)

- (NSString *)tag {
    return self.tag;
}

- (void)setTag:(NSString *)tag {
    self.tag = tag;
}
@end

3, 访问Category添加的tag属性

UIImage *image = [UIImage imageNamed:@""];
[image setTag:@"100"];
NSLog(@"tag:%@", [image tag]);

打印信息为:

2015-08-12 15:17:10.321 InformPub[16828:1373803] CUICatalog: Invalid asset name supplied: 
2015-08-12 15:17:10.321 InformPub[16828:1373803] tag:(null)

看到了没有,我们设置了tag值,完全没有用。那么有没有什么办法可以给Category添加属性字段呢?请看下面:

Category添加字段(Runtime方法)

1,编写Category头文件,还是以UIImage为例


//
//  UIImage+category.h
//  
//
//  Created by Linf on 15-5-19.
//  Copyright (c) 2015年 Linf. All rights reserved.
//
#import <UIKit/UIKit.h>

@interface UIImage (category)

// 在UIImage中新建一个tag属性
@property (nonatomic, copy) NSString *tag;

@end

2,编写Category源文件

//
//  UIImage+category.m
//  
//
//  Created by Linf on 15-5-19.
//  Copyright (c) 2015年 Linf. All rights reserved.
//

#import "UIImage+category.h"

static const void *tagKey = &tagKey;

@implementation UIImage (category)

- (NSString *)tag {
    return objc_getAssociatedObject(self, tagKey);
}

- (void)setTag:(NSString *)tag {
    objc_setAssociatedObject(self, tagKey, tag, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end

3, 访问Category添加的tag属性

UIImage *image = [UIImage imageNamed:@""];
[image setTag:@"100"];
NSLog(@"tag:%@", [image tag]);

打印信息为:

2015-08-12 14:57:58.777 InformPub[16741:1271788] tag:100

到这里代码就添加完成了,Category就可以添加属性字段了。这里面用到了objective-c的Runtime。如果有不了解Runtime的小伙伴,可以参考以下网站:http://southpeak.github.io/blog/2014/10/25/objective-c-runtime-yun-xing-shi-zhi-lei-yu-dui-xiang/

相关文章

网友评论

  • 佳佳Nice:- (NSString *)tag {
    return self.tag;
    }
    self.tag是点语法吧,点语法是调getter方法吧?自己调自己???
  • _RichardLee:用runtime 执行出来tag 还是 null 是什么情况?
    书签123:楼主少了两个地址符号,还有如果之前用nonatomic修饰变量的话,后面应该用OBJC_ASSOCIATION_COPY。
    enum {
    OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用

    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性

    OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性

    OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性

    OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
    };

    代码如下就可以了
    - (NSString *)tag {
    return objc_getAssociatedObject(self, &tagKey);
    }

    - (void)setTag:(NSString *)tag {
    objc_setAssociatedObject(self,& tagKey, tag, OBJC_ASSOCIATION_COPY);
    }
    zuolingfeng:@_JasonLee 一年前写的,当时是可以的,现在好像不行了,刚重新运行了下。
  • aa58d1253852:- (void)setTag:(NSString *)tag {
    self.tag = [tag copy];
    }
    常规方法这样写会造成死循环的
    沈悦:对啊 ,这不是死循环代码么
  • 骨古:为什么我看到UIView扩展,比如加一个属性 CGFloat top 然后在.m文件里 就可以用get set方法返回呢!为什么不用objc_getAssociatedObject?
    Lee_How:@骨古 我的猜想是:因为OC代码最终会转化为C代码运行,所以上面的代码最终会转化成objc_getAsscoiatedObjcet()的形式运行,只是两种不同的写法,objc_getAsscoiatedObjcet是直接操作的底层
    AppleIdGX:@骨古 一般好像都是这样的:
    - (CGFloat) top
    {
    return self.frame.origin.y;
    }

    - (void) setTop: (CGFloat) newtop
    {
    CGRect newframe = self.frame;
    newframe.origin.y = newtop;
    self.frame = newframe;
    }
    不是直接返回self.top
  • leftwater:说白了 类别不能扩展属性 是不能创建对应的实例变量

本文标题:IOS下Category添加属性字段

本文链接:https://www.haomeiwen.com/subject/scwiqttx.html