分类和类都可以添加方法和属性
- 属性
分类通过runtime添加属性
类直接添加 - 方法
添加方式一样
生成
类中生成的有: 成员变量_ivar_list_t 属性变量:_prop_list_t 方法:_method_list_t(setter 和getter)
这里给出TestExpand 以及他的两个分类TestExpand+test TestExpand+Additions
TestExpand
TestExpand+test
TestExpand+Additions
其中TestExpand 有属性以及方法
TestExpand.h
@interface TestExpand : NSObject
@property(nonatomic, copy) NSString *mustProperty;
- (void)testExpanded;
@end
TestExpand.m
- (void)setMustProperty:(NSString *)mustProperty {
NSLog(@"这是类自己的===mustProperty");
mustProperty = mustProperty;
}
- (NSString *)mustProperty {
NSLog(@"这是类自己的");
return _mustProperty;
}
- (void)testExpanded {
NSLog(@"这是类里面的=======testExpanded");
}
TestExpand+test和TestExpand+Additions有属性和方法
TestExpand+Additions.h
@interface TestExpand (Additions)
@property(nonatomic, copy) NSString *mustProperty;
- (void)testExpanded;
@end
TestExpand+Additions.m
#import "TestExpand+Additions.h"
#import<objc/runtime.h>
static const char * thisisname = "thisisname";
@implementation TestExpand (Additions)
// 使用runtime来给分类添加属性
- (void)setMustProperty:(NSString *)mustProperty {
NSLog(@"这是延展里面的mustProperty");
objc_setAssociatedObject(self, thisisname, mustProperty, OBJC_ASSOCIATION_COPY);
}
- (NSString *)mustProperty {
NSLog(@"这是延展里面的");
return objc_getAssociatedObject(self, thisisname);
}
- (void)testExpanded {
NSLog(@"这是延展里面的=======testExpanded");
}
@end
下比较的是分类和类添加属性之后有什么不同。
extern "C" unsigned long OBJC_IVAR_$_TestExpand$_mustProperty;
struct TestExpand_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString * _Nonnull _mustProperty;
};
//_ivar_list_t
static struct /*_ivar_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count;
struct _ivar_t ivar_list[1];
} _OBJC_$_INSTANCE_VARIABLES_TestExpand __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_ivar_t),
1,
{{(unsigned long int *)&OBJC_IVAR_$_TestExpand$_mustProperty, "_mustProperty", "@\"NSString\"", 3, 8}}
};
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[3];
} _OBJC_$_INSTANCE_METHODS_TestExpand __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
3,
{{(struct objc_selector *)"setMustProperty:", "v24@0:8@16", (void *)_I_TestExpand_setMustProperty_},
{(struct objc_selector *)"mustProperty", "@16@0:8", (void *)_I_TestExpand_mustProperty},
{(struct objc_selector *)"testExpanded", "v16@0:8", (void *)_I_TestExpand_testExpanded}}
};
static struct /*_prop_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[1];
} _OBJC_$_PROP_LIST_TestExpand __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_prop_t),
1,
{{"mustProperty","T@\"NSString\",C,N,V_mustProperty"}}
};
extern "C" unsigned long int OBJC_IVAR_$_TestExpand$_mustProperty __attribute__ ((used, section ("__DATA,__objc_ivar"))) = __OFFSETOFIVAR__(struct TestExpand, _mustProperty);
//setter
static void _I_TestExpand_setMustProperty_(TestExpand * self, SEL _cmd, NSString * _Nonnull mustProperty) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_539e20_mi_0);
mustProperty = mustProperty;
}
// getter
static NSString * _Nonnull _I_TestExpand_mustProperty(TestExpand * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_539e20_mi_1);
return (*(NSString * _Nonnull *)((char *)self + OBJC_IVAR_$_TestExpand$_mustProperty));
}
// 方法实现
static void _I_TestExpand_testExpanded(TestExpand * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_539e20_mi_2);
}
上面得到用clang得到的
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc TestExpand+Additions.m -o TestExpand+Additions-arm64.cpp
分类中生成的有:属性变量:_prop_list_t 方法:_method_list_t(setter 和getter)
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[3];
} _OBJC_$_CATEGORY_INSTANCE_METHODS_TestExpand_$_Additions __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
3,
{{(struct objc_selector *)"setMustProperty:", "v24@0:8@16", (void *)_I_TestExpand_Additions_setMustProperty_},
{(struct objc_selector *)"mustProperty", "@16@0:8", (void *)_I_TestExpand_Additions_mustProperty},
{(struct objc_selector *)"testExpanded", "v16@0:8", (void *)_I_TestExpand_Additions_testExpanded}}
};
// 属性
static struct /*_prop_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[1];
} _OBJC_$_PROP_LIST_TestExpand_$_Additions __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_prop_t),
1,
{{"mustProperty","T@\"NSString\",C,N"}}
};
// setter
static void _I_TestExpand_Additions_setMustProperty_(TestExpand * self, SEL _cmd, NSString * _Nonnull mustProperty) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_Additions_d05806_mi_0);
objc_setAssociatedObject(self, thisisname, mustProperty, OBJC_ASSOCIATION_COPY);
}
// getter
static NSString * _Nonnull _I_TestExpand_Additions_mustProperty(TestExpand * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_Additions_d05806_mi_1);
return objc_getAssociatedObject(self, thisisname);
}
// 方法实现
static void _I_TestExpand_Additions_testExpanded(TestExpand * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_b0_wtsz92hn2qg2znkty6jcjtj40000gn_T_TestExpand_Additions_d05806_mi_2);
}
通过调用我们可以看出
TestExpand *expand = [[TestExpand alloc]init];
expand.mustProperty = @"99999";
[expand testExpanded];
NSLog(@"mustProperty====%@",expand.mustProperty);
调用打印结果为:
这是延展里面的mustProperty
这是延展里面的=======testExpanded
这是延展里面的
mustProperty====99999
我们可以看出类中的属性方法被分类中的属性方法所覆盖。也就是说类本身的方法没有被执行,这里说的覆盖和我们说的值覆盖不一样。我们在声明方法和属性的时候,这个时候告诉编译器我们有这样一个属性和方法。当在进行消息转发的时候优先调用分类里的方法和属性。
那么这里有一个问题:两个不同分类里面的属性和方法都一样的情况下是怎么执行的呢?
答:这和分类的编译顺序有关。编译顺序在 TARGETS->Build Phases->Compile Sources
分类具有相同的方法和属性的时候优先编译的被覆盖。
网友评论