OC-分类(Category)

分类(Category)是OC中的特有语法,它是表示一个指向分类的结构体的指针。原则上它只能增长方法,不能增长成员(实例)变量。markdown

Category的做用

为已经存在的类添加方法。能够在不修改原来类的基础上,为一个类 扩展方法。最主要的应用:给系统自带的类 扩展方法。this

  • 注意

1.分类中只能添加“方法”,不能增长成员变量。分类中的能够写@property, 但不会生成setter/getter方法, 也不会生成实现以及私有的成员变量,会编译经过,可是引用变量会报错。spa

2.分类中能够/只能访问原有类中.h中的属性。若是想要访问本类中的私有变量,分类和子类同样,只能经过方法来访问。ssr

3.在本类和分类有同名方法时,优先调用分类的方法。同名方法调用的优先级为分类 > 本类 > 父类3d

4.若是多个分类中都有和原有类中同名的方法,那么调用该方法的时候执行谁由编译器决定;编译器会执行最后一个参与编译的分类中的方法。指针

分类方法不会覆盖掉原来类中的方法,而是共存的。可是分类中的方法在前面,原来的类中的方法在后面,调用的时候,就会调用分类中的方法,若是多个分类有一样的方法,后编译的分类会调用。code

建立分类

例如,建立一个UIView的分类:orm

-

-

在新建的文件的.h中声明新方法,在.m中具体实现方法 格式:对象

@interface 待扩展类的类名(分类名字)
/*方法声明*/
@end
@implementation 待扩展类的类名(分类名字)
/*方法实现*/
@end
复制代码

底层原理

编译完以后每个分类都会生成一个结构体category_t ,里面存储着分类的对象方法、类方法、属性、协议信息。在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象、元类对象中)继承

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
复制代码

案例

UIImage的分类,添加扩展方法更改图片大小。

.h中

#import <UIKit/UIKit.h>

@interface UIImage (Size)

- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize ;


@end
复制代码

.m中

#import "UIImage+Size.h"

@implementation UIImage (Size)


- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

@end
复制代码

分类(Category)和类扩展(extension)的关系

1.类扩展(extension)是Category的一个特例,有时候也被称为匿名分类。他的做用是为一个类添加一些私有的成员变量和方法。 2.和分类不一样,类扩展便可以声明成员变量又能够声明方法。 3.分类的小括号中必须有名字

Class Extension在编译的时候,它的数据就已经包含在类信息中。 Category是在运行时,才会将数据合并到类信息中。

其余

  • Category中有load方法吗?

有load方法,load方法在runtime加载类、分类的时候调用。load方法能够继承,可是通常状况下不会主动去调用load方法,都是让系统自动调用。