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