Category

原创 2015年08月19日 16:39:15

在创建iOS的特有Objective-C 文件的时候我们可以看到Category和Extentsion


Category相信是不难学习的,并且非常重要,可以动态地对OC的类添加方法,为什么称为动态,例如,如果声明一个关于NSData的类目并且在里面实现了两个方法,是不是每一个NSData的相关子类都有了这个类目特性,不,你可以不导入头文件,这时候就好像压根没有实现。

在输入File名字之后,Xcode会自动地帮你创建  “Class” + “File Name”  这种结构,并且其.h .m文件如下:

#import <Foundation/Foundation.h>

@interface NSString (Extend)

@end

#import "NSString+Extend.h"

@implementation NSString (Extend)

@end

而最基本的类UIView,都有大量这样的形式的声明:

@interface UIView(UIViewRendering)

- (void)drawRect:(CGRect)rect;

- (void)setNeedsDisplay;
- (void)setNeedsDisplayInRect:(CGRect)rect;


我们都知道,协议是不允许添加实例变量的,那Category呢?直接动手敲


非常明显啦,instance variables may not be placed in categories , 实例变量不能被放置于分类中


我们先来看看UITableView中一个非常实用的分类:

// This category provides convenience methods to make it easier to use an NSIndexPath to represent a section and row
@interface NSIndexPath (UITableView)

+ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;

@property(nonatomic,readonly) NSInteger section;
@property(nonatomic,readonly) NSInteger row;

@end

见:http://www.cocoachina.com/bbs/read.php?tid=292400

如果你觉得上面section 和 row为什么能放,哈哈,你就和我一样too young too naive啦,如果看懂了上面的解释,你就该懂了,就是getset方法理解的不透彻,属性变量时自动地声明了getset方法,所以上面的@property不是着重于 “变量” 这一侧,而是重于方法这一侧,所以我们为什么能直接地用:

indexPath.section
indexPath.row

其实是使用了NSIndexPath的get方法来取得 值 而已,而且很明显是readonly只能调用它的get方法而不能调用它的set方法。这种情况下,是不会生成实例变量的。

同理于Protocol协议中的实例变量和属性变量的区别也是同样原理。

见:http://blog.csdn.net/itianyi/article/details/8618128

这里文章中部分也阐述了。

但是注意的是,即使不能为分类添加实例变量,但是分类是包含相关类本身的所有属性和实例变量的,所以可以在分类的方法实现上大胆使用!



那如果我们非得添加实例变量呢? 从网上面收集到的信息大概有两类。

1.使用匿名分类(扩展):

其实这里的匿名分类可以说和分类其实没多大关系,具体使用就是把@interface写在实现文件里,并且将:superClass 改成 ()罢了,所谓匿名就是不要名字,这时候注意,这里的实例变量和方法声明都是私有的。

2.使用全局变量

这个没去研究。

3.通过Associative References来添加

http://www.cnblogs.com/wengzilin/p/4331685.html?utm_source=tuicool



接下来是Category和Extension有什么区别。

动手建立一个关于NSString类的ExtensionTest,如下:


发现并没有.m文件。

这里说到了一点:把代码写到原始类的.m文件中。


经过网上资料的了解,原来Extension和匿名Category非常非常像,简直可以直说就是,其实自己看就知道,创建了之后的格式基本一样。总结来说就是:扩展(extension)可以添加成员变量, 扩展(extension)就是匿名的Category。



那我们到底什么时候需要继承子类实现新方法什么时候需要使用分类呢?

1.如果需要动用到新的实例变量,理所当然用继承子类 

2.如果需要大批量增加类的方法并不改变类本身(不能和原有方法重名,会权重于分类,从而覆盖原有方法),使用分类



实战,在做仿微信键盘的时候遇到一个分类的实现和使用:

1.

#import <UIKit/UIKit.h>

@interface UIImage (StrethImage)

+ (id)strethImageWith:(NSString *)imageName;

@end

#import "UIImage+StrethImage.h"

@implementation UIImage (StrethImage)

+ (id)strethImageWith:(NSString *)imageName
{
    UIImage *image=[UIImage imageNamed:imageName];
    
    image=[image stretchableImageWithLeftCapWidth:image.size.width*0.5 topCapHeight:image.size.height*0.5];
    
    return image;
}
@end

self.backImageView.image = [UIImage strethImageWith:@"toolbar_bottom_bar.png"];

原来就是增加了拉伸图片以适配的功能,与其说增加,不如说是封装了如此的功能,如果我们拆开在.m中也是可以实现的,所以这里的分类更多的是一种规范,封装的作用!


2.

做仿微信键盘的时候见到这个方法,点进去endEditing一看:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}
这个endEditing是一个很显然的扩展:

@interface UIView (UITextField)
- (BOOL)endEditing:(BOOL)force;    // use to make the view or any subview that is the first responder resign (optionally force)
@end

因为是原生类我们不知道其实现,但是有趣的是,且看它处于的位置和命名规律:

可以看到它放在UITextField类的头文件来声明,并且分类的名字为UITextField,结合在实际中的使用就会知道这里的分类的作用是一种相互合作,相互补充的作用!

补充:这些叫做  category methods !






参考资料:

基本语法:http://www.cnblogs.com/kenshincui/p/3869639.html#category

整理和解释:http://blog.sina.com.cn/s/blog_a2c098b50101gsn0.html

突破添加实例变量的瓶颈:http://www.cnblogs.com/wengzilin/p/4331685.html?utm_source=tuicool

实例变量和属性变量在分类的纠结:http://www.cocoachina.com/bbs/read.php?tid=292400



版权声明:本文为博主原创文章,未经博主允许不得转载。

iOS category内部实现原理

转载自:http://tech.meituan.com/DiveIntoCategory.html 摘要 无论一个类设计的多么完美,在未来的需求演进中,都有可能会碰到一些无法预测的情况。那...
  • a316212802
  • a316212802
  • 2015年11月17日 22:28
  • 8578

Category的用法

什么是Category Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的,在很多情形下Category也是比创建子类更优的选择。新添加的方法同样也会被被扩展的类的所有子类自动继...
  • u014766462
  • u014766462
  • 2014年12月03日 13:07
  • 391

iOS category内部实现原理

转载自:http://blog.csdn.net/a316212802/article/details/49894421 感觉写得很好,跟大家分享下 摘要 无论一个类设计...
  • tyuersunshine
  • tyuersunshine
  • 2016年04月19日 22:02
  • 274

Intent的Component,Action和Category属性详解-android学习之旅(五十)

Component属性 代码示例public class MainActivity extends Activity{ @Override protected void onCr...
  • u010321471
  • u010321471
  • 2015年06月26日 22:42
  • 1143

Intent filter 关于Action、Category属性详解---附带实例源码

如果一个 Intent 请求在一片数据上执行一个动作, Android 如何知道哪个应用程序(和组件)能用来响应这个请求呢? Intent Filter就是 用来注册 Activity 、 Servi...
  • a13429921973
  • a13429921973
  • 2013年07月08日 15:17
  • 15516

由category为什么不能添加属性所想到的

在category里添加属性的情况?在类中使用@property,系统会自动生成带“_”的成员变量和该变量的setter和getter方法。也就是说,属性相当于一个成员变量加getter和setter...
  • lwq718691587
  • lwq718691587
  • 2017年03月09日 17:52
  • 282

iOS 使用category将复杂的类拆分

在开发过程中,我们应该尽量保证代码的整洁性,方法尽量的简短,一个方法只做一件事情,而类也不应该过于复杂。很多时候,我们会一直往一个类里面添加代码,最终,这个类可能成为一个“庞然大物”。在iOS开发中,...
  • u011367651
  • u011367651
  • 2015年08月06日 21:34
  • 942

类别(Category)的作用(零)

类别——一种为现有的类添加新方法的方式。 利用Objective-C的动态运行时分配机制,可以为现有的类添加新方法,这种为现有的类添加新方法的方式称为类别(catagory)。他可以为任何类添加新的...
  • lxubin
  • lxubin
  • 2016年07月31日 11:23
  • 1297

LTE终端能力等级 Category

Category终端能力等级,表明了终端所支持的数据处理能力(下载、上传速率)、最大的空分复用、调制编码能力等。   详细可参考 3GPP 36.306。在R8版本中定义了5类终端,在R10中定义了8...
  • shij19
  • shij19
  • 2016年10月27日 15:48
  • 3460

讲解Intent中的四个重要属性——Action、Data、Category、Extras

1 前言Intent作为联系各Activity之间的纽带,其作用并不仅仅只限于简单的数据传递。通过其自带的属性,其实可以方便的完成很多较为复杂的操作。例如直接调用拨号功能、直接自动调用合适的程序打开不...
  • mffandxx
  • mffandxx
  • 2017年01月03日 15:00
  • 685
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Category
举报原因:
原因补充:

(最多只允许输入30个字)