iOS中分类(Category)和类扩展(Extension)的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS中分类(Category)和类扩展(Extension)的区别相关的知识,希望对你有一定的参考价值。

参考技术A 一、分类(Category):

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

这个结构体主要包含了分类定义的实例方法与类方法,其中instance_methods 列表是 objc_class 中方法列表的一个子集,而class_methods列表是元类方法列表的一个子集。
但在这个结构体里面,没有属性列表!

二、类扩展(class extension)

Extension是Category的一个特例。类扩展与分类相比只少了分类的名称,所以称之为“匿名分类”。

1、类扩展不仅可以增加方法,还可以增加实例变量(或者属性)
2、类扩展所声明的方法必须依托对应类的实现部分来实现。

同一个头文件中的类和类扩展名(类别)

【中文标题】同一个头文件中的类和类扩展名(类别)【英文标题】:Class and class extension (category) in the same header file 【发布时间】:2015-02-24 06:04:27 【问题描述】:

当我查看 Cocoa Touch API 时,我可以在同一个头文件中找到一些与类别一起声明的类,例如

@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>

@property (readonly) NSUInteger count;
// and some other properties

@end

@interface NSArray (NSExtendedArray)

@property (readonly, copy) NSString *description;
// and some other properties

@end

现在我正在尝试对我的班级做同样的事情,如下所示:

@interface ARCTextbook : NSObject

@property (nonatomic) NSInteger ID;
@property (nonatomic) NSString *name;

@end

@interface ARCTextbook (Student)

@property (nonatomic) NSInteger studentID;
@property (nonatomic, getter=isUsed) BOOL used; // Used by a student?

@end

但是,当我尝试访问 studentIDused 属性时,出现无法识别的选择器错误。我错过了什么吗?

干杯。

【问题讨论】:

【参考方案1】:

这是关联对象,您可以参考以下文档:

http://www.davidhamrick.com/2012/02/12/Adding-Properties-to-an-Objective-C-Category.html

How to store not id type variable use a objc_getAssociatedObject/objc_setAssociatedObject?

ARCTextbook.h

#import <Foundation/Foundation.h>

@interface ARCTextbook : NSObject
@property (nonatomic) NSInteger ID;
@property (nonatomic) NSString *name;
@end

@interface ARCTextbook (Student)

@property (nonatomic) NSInteger studentID;
@property (nonatomic, getter=isUsed) BOOL used; // Used by a student?

@end

ARCTextbook.m

#import "ARCTextbook.h"
#import <objc/runtime.h>

@implementation ARCTextbook

@end

static NSString *kStudentID = @"kStudentID";
static NSString *kUsed = @"kUsed";

@implementation ARCTextbook (Student)
@dynamic studentID;
@dynamic used;

- (void)setStudentID:(NSInteger)aStudentID 
    objc_setAssociatedObject(self, (__bridge const void *)(kStudentID), @(aStudentID), OBJC_ASSOCIATION_RETAIN_NONATOMIC);


- (NSInteger)studentID 
    return [objc_getAssociatedObject(self, (__bridge const void *)(kStudentID)) integerValue];


- (void)setUsed:(BOOL)aUsed 
    objc_setAssociatedObject(self, (__bridge const void *)(kUsed), @(aUsed), OBJC_ASSOCIATION_RETAIN_NONATOMIC);


- (BOOL)isUsed 
    return [objc_getAssociatedObject(self, (__bridge const void *)(kUsed)) boolValue];


@end

ViewController.m

#import "ViewController.h"
#import "ARCTextbook.h"

@implementation ViewController

- (void)viewDidLoad 
    [super viewDidLoad];

    // Do any additional setup after loading the view.
    ARCTextbook *t = [[ARCTextbook alloc] init];
    t.studentID = 2;
    t.used = YES;



@end

【讨论】:

你试过运行代码吗?我在运行时遇到了无法识别的选择器错误。 您好,感谢您的回答。我想除了使用关联对象没有办法解决这个问题!

以上是关于iOS中分类(Category)和类扩展(Extension)的区别的主要内容,如果未能解决你的问题,请参考以下文章

iOS之深入解析类加载的底层原理:分类如何加载到类以及分类和类的配合使用

iOS中的分类和扩展

iOS中分类(Category)、扩展(Extention)和继承(Inheritence)的区别?

iOS之分类(category)

iOS分类(category)、类扩展(extension)、继承的区别

iOS中分类(category)的使用