一、 分類和類擴(kuò)展區(qū)別
1. 分類實(shí)現(xiàn)原理
- Category編譯之后的底層結(jié)構(gòu)是struct category_t,里面存儲(chǔ)著分類的對(duì)象方法、類方法、屬性、協(xié)議信息
- 在程序運(yùn)行的時(shí)候,runtime會(huì)將Category的數(shù)據(jù),合并到類信息中(類對(duì)象、元類對(duì)象中)
2. Category和Class Extension的區(qū)別是什么?
- Class Extension在編譯的時(shí)候,它的數(shù)據(jù)就已經(jīng)包含在類信息中
- Category是在運(yùn)行時(shí),才會(huì)將數(shù)據(jù)合并到類信息中
二、 分類為啥不能添加成員變量
先看Category的底層結(jié)構(gòu)
struct _category_t {
const char *name;
struct _class_t *cls;
const struct _method_list_t *instance_methods; // 對(duì)象方法列表
const struct _method_list_t *class_methods; // 類方法列表
const struct _protocol_list_t *protocols; // 協(xié)議列表
const struct _prop_list_t *properties; // 屬性列表
};
1.從結(jié)構(gòu)體可以知道,有
屬性列表,所以分類可以聲明屬性,但是分類只會(huì)生成該屬性對(duì)應(yīng)的get和set的聲明,沒有去實(shí)現(xiàn)該方法。
2.結(jié)構(gòu)體沒有成員變量列表,所以不能聲明成員變量。
1. Category的加載處理過程
- 1.通過Runtime加載某個(gè)類的所有Category數(shù)據(jù)
- 2.把所有Category的方法、屬性、協(xié)議數(shù)據(jù),合并到一個(gè)大數(shù)組中,后面參與編譯的Category數(shù)據(jù),會(huì)在數(shù)組的前面
- 3.將合并后的分類數(shù)據(jù)(方法、屬性、協(xié)議),插入到類原來數(shù)據(jù)的前面
三、關(guān)聯(lián)對(duì)象給分類添加屬性
代碼實(shí)現(xiàn)如下
- Student+Extern.m
#import "Student+Extern.h"
#import <objc/runtime.h>
static NSString *nameKey = @"nameKey"; //定義一個(gè)key值
@implementation Student (Extern)
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY);
}
- (NSString *)name {
return objc_getAssociatedObject(self, &nameKey);
}
@end
外界調(diào)用
Student *stu = [[Student alloc] init];
stu.name = @"喬碧蘿";
NSLog(@"name = %@",stu.name);
運(yùn)行結(jié)果 - 關(guān)聯(lián)成功

但是注意,以上代碼僅僅是手動(dòng)實(shí)現(xiàn)了setter/getter方法,但調(diào)用_成員變量依然報(bào)錯(cuò)。
更多:iOS面試題合集