美文网首页iOS开发iOS学习iOS开发
NSObject 类和 NSObject 协议

NSObject 类和 NSObject 协议

作者: 花与少年_ | 来源:发表于2017-05-05 17:28 被阅读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类

    相关文章

      网友评论

        本文标题:NSObject 类和 NSObject 协议

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