这是我参与「第四届青训营 」笔记创作活动的的第2天。
NSObject 类
1. 分配内存空间 & 初始化
在创建任何一个对象时,都会用到这两个方法 alloc 和 init。
首先调用的静态方法 alloc,系统会为这个对象分配内存并返回一个空的实例,之后再调用 init 实例方法进行初始化,通常子类也会覆盖这个方法去做相应的初始化,还有另外一个用法 new,它等于 alloc + init,我们自己定义的类或是其他系统类,也都可以使用 new 去创建对象,代替 alloc + init。
// NSObject.h
@interface NSObject <NSObject> {
/** 为新对象分配内存空间 */
+ (instancetype)alloc;
/** 初始化对象 */
- (instancetype)init;
/** 为新对象分配内存空间并初始化, 等于[[NSObject alloc] init] */
+ (instancetype)new;
}
//main.m
MyClass *myClass1 = [[MyClass alloc] init];
// 等同于
MyClass *myClass2 = [MyClass new];
2. 发送消息(方法调用)
一种方法调用的方式是通过 performSelector 调用,它不会在编译时做任何的较验,也就是可以去创建一个该对象没有在 interface 声明的方法选择器并调用,由于没有编译器把关,如果该方法确实没有实现就会崩溃,所以一般在使用时会搭配 respondsToSelector 提前确认该对象是否响应消息。
// NSObject.h
@protocol NSObject
/** 发送指定的消息给对象, 返回消息执行结果(相当于方法调用) */
- (id)performSelector:(SEL)aSelector;
/** 发送带一个参数的消息给对象, 返回消息执行结果(相当于方法调用) */
- (id)performSelector:(SEL)aSelector withObject:(id)object;
/** 判断对象是否能够调用给定的方法 */
- (BOOL)respondsToSelector:(SEL)aSelector;
@end
// main.m
// 先判断对象是否能调用方法,再执行调用方法
if ([myClass1 respondsToSelector:@selector(sayHello)]) {
// 调用无参无返回值方法
[myClass1 performSelector:@selector(sayHello)];
}
// 可以用于调用私有方法
if ([myClass1 respondsToSelector:@selector(private_method)]) {
[myClass1 performSelector:@selector(private_method)];
}
3. 类关系判断
判断对象与对象之间类的关系,以及获取对象的类的方法。
类型 Class,不是对象,是一个类的型别。
// NSObject.h
/** 获取当前对象的类 */
- (Class)class;
/** 获取当前对象的类 */
- (Class)superclass;
/** 判断对象是否是给定类或给定类子类的实例 */
- (BOOL)isKindOfClass:(Class)aClass;
/** 判断对象是否是给定类的实例 */
- (BOOL)isMemberOfClass:(Class)aClass;
/** 判断对象是否遵从给定的协议 */
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
// 字典对应的不确定类型
NSObject *getValue = [dictionary1 objectForKey:@"key1"];
if ([getValue isKindOfClass:NSString.class]) {
// 确定是NSString 在转型成NSString
NSString *strValue = (NSString *)getValue;
[strValue length];
} else if([getValue isKindOfClass:ByteDancer.class]) {
// 确定是ByteDancer 在转型成ByteDancer
ByteDancer *byteDacner1 = (ByteDancer *)getValue;
[byteDacner1 sayHello];
} else {
NSLog(@"unkown class");
}