iOS开发iOS学习iOS开发

NSObject 类和 NSObject 协议

2017-05-05  本文已影响171人  花与少年_
为什么可以重名?

在分析这两个的区别之前,我们先思考一个问题,为啥这两个长一样的东西不会发生命名冲突呢?
因为在 OC 中,类和协议是存在于不同命名空间的,所以一个作为类,一个作为协议,他们是可以重名的。

OC 中的基类

NSObject是基类,它再也没有超类。但是 OC 不像 Java 只有一个基类,OC 有多个基类,除了 NSObject 之外,还含有一个 NSProxy 基类和其他各种各样的基类。

NSObject 协议

拥有多个基类之后,也就引出了 NSObject 协议存在的理由,NSObject 协议规定了一些所有基类都需要实现的基本方法和属性,比如isEqual: 、isKindOfClass、respondsToSelector等,当然还有内存管理的方法 retain 、release、autorelease、retainCount等,这样就定义了一个相对统一的接口和 OC 对象都可以响应的方法。
我们可以看到这两个基类都遵从 NSObject 协议。

@interface NSProxy <NSObject>
@interface NSObject <NSObject>
NSProxy 基类

NSObject 基类除了遵从 NSObject 协议之外,还实现了一大堆别的方法,有时候,我们自定义的类并不需要这些方法。
比如我们自定义一些类,目的是进行一些消息转发,这个时候我们就可以让他继承自 NSProxy 基类,代表一些代理、转发作用的类,避免继承自 NSObject 引入大量不需要的方法。
我们可以看到 NSProxy 有这两个方法可以帮助实现消息转发:

- (void)forwardInvocation:(NSInvocation *)invocation;
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");

现在让我们来尝试一下,首先定义一个类继承自 NSProxy,定义一个 object 属性,并且实现上面所说的两个方法:

@property (nonatomic,strong)NSObject *object;

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *methodSignature;
    if (self.object) {
        methodSignature = [self.object methodSignatureForSelector:sel];
    }else{
        methodSignature = [super methodSignatureForSelector:sel];
    }
    return methodSignature;
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    if (self.object) {
        [invocation setTarget:self.object];
        [invocation invoke];
    }
}

关于 NSInvocation 函数的调用可以参考小的之前写的这篇博文

然后定义一个吃瓜群众类……将 Proxy 类收到的方法调用都传给他。

#import "Dog.h"

@implementation Dog
- (void)eat
{
    NSLog(@"我是🐶,我想来点狗粮");
}
@end

实例化 Proxy 和 Dog,并且给 Proxy 传一个eat调用,可以看到,这个消息最终传给了 Dog:

ZNProxy *proxy = [ZNProxy alloc];
Dog *dog = [[Dog alloc] init];
//设置proxy的object为dog,以后proxy收到的消息最终都会传给dog
proxy.object = dog;

[proxy performSelector:@selector(eat)];
消息传给了Dog类
上一篇下一篇

猜你喜欢

热点阅读