zoukankan      html  css  js  c++  java
  • iOS中OC给Category加入属性

    引:

    非常多人知道能够用Category给已有的类加入一些新方法,可是不同于swift中的extension,Objective-C中的Category(类别)是不支持直接加入属性的。那假设就是须要加入新的属性怎么办呢?有一个办法。使用Runtime中的关联对象技术就能够实现。关于Runtime的说明能够查看这篇博客:传送门:OC中Runtime浅析

    Category(类别):

    对于不熟悉Category的人,这里也先说明一下Category是什么以及怎么创建Category。

    由于一些特殊的须要,我们可能要给现有的类加入一些新的方法。这个需求用继承也能够做到。可是会显得比較重。这时候就能够用Category来达到目的,创建一个已有类的Category,能够给这个类加入你须要的方法,在使用的时候,仅仅须要import你创建的Category,在使用的时候还是使用原来的类。可是你会惊奇的发现他支持你自己在Category中加入的方法。

    我们看到的一些名为相似“UINavigationController+Cloudox.h”的文件就是类别了。

    那么怎么创建类别呢?

    在project中按住command+N来加入新文件,选择Objectiv-C File:

    在出来的界面中的File Type选择Category,就是创建类别文件了,File填写我们要加在类别尾巴上的名字,Class选择你要加入类别的已有类。这里我们为UINavigationController加入类别:

    类别文件这样就创建成功了。

    加入属性

    类别能够为已有的类加入方法,可是却不能直接加入属性,由于即使你加入了@property。它既不会生成实例变量,也不会生成setter、getter方法,即使你加入了也无法使用。

    所以我们首先须要自己去加入setter、getter方法。这个好办,直接在.m文件中加就能够了,可是要真正加入能够使用的属性,还须要利用Runtime来关联对象,关于关联对象的技术能够看传送门:OC中Runtime浅析,这里仅仅讲怎么用来加入属性,我们在setter方法里关联一个对象。在getter方法里获取相应key关联的对象。就能够啦,代码例如以下,非常easy:

    //UINavigationController+Cloudox.h文件
    #import <UIKit/UIKit.h>
    
    @interface UINavigationController (Cloudox)
    
    @property (copy, nonatomic) NSString *cloudox;
    
    @end
    
    //UINavigationController+Cloudox.m文件
    #import "UINavigationController+Cloudox.h"
    #import <objc/runtime.h>
    
    @implementation UINavigationController (Cloudox)
    
    //定义常量 必须是C语言字符串
    static char *CloudoxKey = "CloudoxKey";
    
    -(void)setCloudox:(NSString *)cloudox{
        /*
         objc_AssociationPolicy參数使用的策略:
         OBJC_ASSOCIATION_ASSIGN;            //assign策略
         OBJC_ASSOCIATION_COPY_NONATOMIC;    //copy策略
         OBJC_ASSOCIATION_RETAIN_NONATOMIC;  // retain策略
    
         OBJC_ASSOCIATION_RETAIN;
         OBJC_ASSOCIATION_COPY;
         */
        /*
         关联方法:
         objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
    
         參数:
         * id object 给哪个对象的属性赋值
         const void *key 属性相应的key
         id value  设置属性值为value
         objc_AssociationPolicy policy  使用的策略,是一个枚举值,和copy,retain。assign是一样的,手机开发一般都选择NONATOMIC
         */
    
        objc_setAssociatedObject(self, CloudoxKey, cloudox, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    -(NSString *)cloudox{
        return objc_getAssociatedObject(self, CloudoxKey);
    }
    
    
    @end

    注意要使用Runtime须要 import runtime 的框架,如代码所看到的。

    如今我们试试效果,我们依照寻常的方式用UINavigationController包装一个控制器作为根视图:

    // AppDelegate
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        ViewController *vc = [[ViewController alloc] init];
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
        self.window.rootViewController = nav;
        return YES;
    }

    这个视图控制器中我们须要导入我们的类别文件。然后我们就会发现我们能够通过self.navigationController获取到我们新加入的名为“cloudox”的属性了!我们能够给这个NSString类型的属性赋值,然后获取它进行显示:

    #import "UINavigationController+Cloudox.h"
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.title = @"Demo";
        self.view.backgroundColor = [UIColor lightGrayColor];
    
        // 给UINavigationController新加的属性赋值
        self.navigationController.cloudox = @"Hey,this is category's new property!";
    
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width-300)/2, 100, 300, 50)];
        label.textColor = [UIColor whiteColor];
        label.textAlignment = NSTextAlignmentCenter;
        label.text = self.navigationController.cloudox;
        [self.view addSubview:label];
    }

    效果例如以下:

    正常获取到而且显示,非常棒。

    以上就是给Category加入属性的方法啦。不难,仅仅要了解Runtime中的关联对象技术就能够轻松达到了。


    演示样例project:https://github.com/Cloudox/CategoryAddPropertyDemo
    版权全部:http://blog.csdn.net/cloudox_

  • 相关阅读:
    扫面线模板
    (动态规划、栈)leetcode 84. Largest Rectangle in Histogram, 85. Maximal Rectangle
    tmux 常见命令汇总
    leetcode 221
    leetcode 319 29
    (贪心)leetcode 392. Is Subsequence, 771. Jewels and Stones, 463. Island Perimeter
    leetcode 982 668
    Python import 同文件夹下的py文件的函数,pycharm报错
    Windows里Anaconda-Navigator无法打开的解决方案
    Windows下 gpu版 Tensorflow 安装
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8288682.html
Copyright © 2011-2022 走看看