Category是什么以及怎么创建Category

    作者:课课家教育更新于: 2017-03-28 18:18:47

         了解OC的都应该知道,在一般情况下,我们是不能向Category中添加属性的,只能添加方法,但有些情况向,我们确实需要向Category中添加属性,而且很多系统的API也有一些在Category添加属性的情况,例如我们属性的UITableView的section和row属性,就是定义在一个名为NSIndexPath的分类里的。 看完后希望对大家有所帮助 如下:

          指引如下:

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

      Category(类别):

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

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

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

      那么怎么创建类别呢?

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

    Category是什么以及怎么创建Category_iOS_移动开发_大数据_课课家教育

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

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

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

      添加属性

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

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

      //UINavigationController+Cloudox.h文件

      #import

      @interface UINavigationController (Cloudox)

      @property (copy, nonatomic) NSString *cloudox;

      @end

      //UINavigationController+Cloudox.m文件

      #import "UINavigationController+Cloudox.h"

      #import

      @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);

      }

      @end123456789101112131415161718192021222324252627282930313233343536373839404142434445464748

      注意要使用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;

      }1234567

      这个视图控制器中我们需要导入我们的类别文件,然后我们就会发现我们能够通过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];

      }12345678910111213141516

      效果如下:

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

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

      小分享:

      GitHub上有很多不错的iOS开源项目,个人认为不错的,有这么几个:

      1. ReactiveCocoa:ReactiveCocoa/ReactiveCocoa · GitHub:

      GitHub自家的函数式响应式编程范式的Objective-C实现,名字听着很高大上,学习曲线确实也比较陡,但是绝对会改变你对iOS编程的认知,首推之。

      2. Mantle:Mantle/Mantle · GitHub:

      又是GitHub自家的产物,轻量级建模的首选,也可以很好的配合CoreData工作。

      3. AFNetworking:AFNetworking/AFNetworking · GitHub:

      iOS7之前,苹果自带的网络库有多难用!matt大神的AFNetworking绝对可以解放你。使用苹果的NSURLRequest及iOS7的NSURLSession,清晰的架构,足够的文档,可以认为是第三方开源库的楷模了。

      4. BlocksKit: pandamonia/BlocksKit 路 GitHub

      本人相当偏爱Functional Programming,Objective-C中的block绝对满足我的口味。但想用好block也不是很容易,如果对block有爱,就请使用这个库吧。

      5. Nimbus:jverkoey/nimbus · GitHub

      第一次关注nimbus是因为Facebook的Three20开源库。可惜Three20库已死,主要作者跳出来,写了nimbus。

      6. pop: facebook/pop · GitHub

      facebook出品的paper,动画效果太好了,赶超apple的原生app一大截。pop就是paper的动画库!

      7. GPUImage: BradLarson/GPUImage ยท GitHub

      iOS7出来时,很多好看的效果,其实都是对图像的各种处理(比如模糊效果)。图像处理看来以后也是iOS开发的必备技能之一了。而GPUImage,就是能快速处理各种图像效果的利器!

          结语如下:

      以上就是给Category增添属性的方法啦,不难,只要了解Runtime中的关联对象技术就可以轻松达到了。如果大家还有相关方面的问题,可以登录课课家教育平台咨询~

课课家教育

未登录

1