Effective Objective-C 2.0 读书笔记------类对象
前言
在学习消息转发之中的动态方法解析,对如何获取实例方法列表和类方法列表有些许疑问。在使用class方法,对NSObject的实例对象使用class方法,和对NSObject直接使用class方法,得到的结果是一样的,都是获得NSObject的类对象。
objcobjc
NSObject *name = [NSObject new];
NSLog(@"1_%@",[name class]);
NSLog(@"2_%@",[NSObject class]);
这是为什么呢?按理来说对[NSObject class]
获取的是元类对象似乎更合逻辑
其实这里[NSObject class]
指的是类本身,而不是所谓的类对象。所以我们对单纯指向的一个类使用一次class方法得到的就是类对象,如果我们想要获得元类对象的话应该对其得到的类对象在进行一次class
在 class
调用时 ,无论是对实例对象还是对类本身调用,最终返回的 都是类对象 (即 NSObject
的类对象)。这意味着 对实例调用 class
方法时,返回的也是该实例所属类的类对象,而不是元类对象。
类对象
说了关于类对象的引入,接下来我们要了解的是,类对象作为一个对象应该是由什么构成的呢?在具体介绍之前,书中还讲了一些基本知识。
每个Objective-C对象实例都是指向某块内存数据的指针 。所以在声明变量时,类型后面要跟一个" * *"字符,在C语言中这个星号代表着指针
NSString *pointerVariable = @"Some string";
对于通用的对象类型id,由于其本身已经是指针了,所以我们能够这样写:
objc
id generic rypedString= @"Somestring";
Id类型本身定义如下:
objc
typedef struct obje_object (
Class isa;
}*id:
每个对象结构体的首个成员是Class 类的变量。该变量定义了对象所属的类, 通常称为"isa" 指针。
类对象的定义如下
objc
typedef struct objc_class {
Class isa; // 类的类型指针,指向类的元类对象
Class super_class; // 指向父类的指针
const char *name; // 类的名字(C 字符串)
long version; // 类的版本信息(通常用来做版本控制)
long info; // 类的元数据,一般用于存储类的一些属性(如是否是 `Meta-Class`)
long instance_size; // 类的实例大小,即实例对象占用的内存大小
struct objc_ivar_list *ivars; // 实例变量列表,指向一个 `objc_ivar_list` 结构体
struct objc_method_list **methodLists; // 方法列表,指向方法表的指针
struct objc_cache *cache; // 方法缓存,存储常用的方法以提高性能
struct objc_protocol_list *protocols; // 协议列表,指向协议列表
} objc_class;
关于isa指针继承链的相关内容,在刚开始接触OC的博客之中就有讲到,我们拿书中给出的图作为例子
isMemberOfClass和isKindOfClass
1. isMemberOfClass:
- 作用 :检查对象是否严格属于 某个类,不包括子类。
- 返回值 :如果对象是指定类的直接实例(即不考虑继承关系),返回
YES
,否则返回NO
。
2. isKindOfClass:
- 作用 :检查对象是否属于 某个类或其子类。
- 返回值 :如果对象是指定类或该类的任何子类的实例,返回
YES
,否则返回NO
。
书中给出的应用
objc
- (NSString*)commaSeparatedStringFromObjects:(NSArray*)array {
NSMutableString *string = [NSMutableString new]; // 创建一个可变字符串用于存储结果
for (id object in array) {
if ([object isKindOfClass:[NSString class]]) {
// 对于NSString类型的对象,直接将其添加到字符串中
[string appendFormat:@"%@,", object];
} else if ([object isKindOfClass:[NSNumber class]]) {
// 对于NSNumber类型的对象,转化为整数并添加到字符串中
[string appendFormat:@"%d,", [object intValue]];
} else if ([object isKindOfClass:[NSData class]]) {
// 对于NSData类型的对象,进行Base64编码后添加到字符串中
NSString *base64Encoded = [object base64EncodedStringWithOptions:0]; // 假设我们有Base64编码的功能
[string appendFormat:@"%@,", base64Encoded];
} else {
// 对于不支持的类型,打印错误消息
NSLog(@"Unsupported type: %@", NSStringFromClass([object class]));
}
}
// 移除字符串最后多余的逗号
if (string.length > 0) {
[string deleteCharactersInRange:NSMakeRange(string.length - 1, 1)];
}
return string;
}