美文网首页
在iOS中分类和类中添加属性和方法的区别

在iOS中分类和类中添加属性和方法的区别

作者: 南风_001 | 来源:发表于2019-08-14 16:00 被阅读0次

分类和类都可以添加方法和属性

  • 属性
    分类通过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

Compile Sources.png

分类具有相同的方法和属性的时候优先编译的被覆盖。

相关文章

  • 在iOS中分类和类中添加属性和方法的区别

    分类和类都可以添加方法和属性 属性分类通过runtime添加属性类直接添加 方法添加方式一样 生成 类中生成的有:...

  • 动态添加属性

    动态向类中加入属性 (未实现的方法并没有在类的MethodList)在分类中只能添加方法,不能添加属性,在分类中声...

  • 类 *分类* 类扩展

    分类:Category iOS中的分类主要的作用就是为类提供扩展,增加一些方法。但是只能添加方法 不能添加属性?我...

  • iOS 类扩展

    类扩张和分类的区别 1、category类别、分类 专门用来给类添加新方法 不能添加成员属性,添加了也不能娶到 可...

  • 分类-Category

    分类-Category 分类的功能 在OC中,我们可以使用分类为类添加方法,属性.也可以覆盖类原有的方法,自己添加...

  • 分类-Category

    分类-Category 分类的功能 在OC中,我们可以使用分类为类添加方法,属性.也可以覆盖类原有的方法,自己添加...

  • 分类的关联属性

    类扩展和分类的区别 category:就是类别,也叫分类,专门用来给类添加新的方法,不能给类添加成员属性,但可以使...

  • iOS-分类(Category)

    在iOS开发中我们常使用Category来给类添加方法或者属性,原理是什么呢. 分类概况 我们先尝试写个分类.NS...

  • OC类目、延展

    类目: 定义:为现有工程中的类和系统类添加新的方法 作用:在类目中添加新的方法及属性和在原类中添加方法和属性是一样...

  • ios中的分类

    在ios中给分类添加属性,可以通过属性关联来实现重写set方法如下: -(NSMutableDictionary ...

网友评论

      本文标题:在iOS中分类和类中添加属性和方法的区别

      本文链接:https://www.haomeiwen.com/subject/tfggjctx.html