• iOS设计模式


    iOS设计模式 - 代理

    原理图

    说明

    1. 代理模式大家都用过,但用抽象基类NSProxy实现代理估计鲜有人用

    2. 本人用NSProxy实现了代理模式,对于理解消息转发机制有点帮助

    源码

    https://github.com/YouXianMing/iOS-Design-Patterns

    //
    //  AbstractProxy.h
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface AbstractProxy : NSProxy
    
    /**
     *  被代理对象
     */
    @property (nonatomic, weak) id  customer;
    
    /**
     *  代理客户
     *
     *  @param customer 实现了某种协议的客户
     *
     *  @return 代理对象
     */
    - (instancetype)initWithCustomer:(id)customer;
    
    @end
    //
    //  AbstractProxy.m
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <objc/runtime.h>
    #import "AbstractProxy.h"
    #import "AbstractExcute.h"
    
    @implementation AbstractProxy
    
    - (instancetype)initWithCustomer:(id)customer {
    
        self.customer = customer;
        return self;
    }
    
    #pragma mark - NSProxy
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        
        if ([self.customer respondsToSelector:aSelector]) {
            
            return [self.customer methodSignatureForSelector:aSelector];
            
        } else {
            
            AbstractExcute *excute = [AbstractExcute shareInstance];
            return [excute methodSignatureForSelector:NSSelectorFromString(@"nullExcute:")];
        }
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        
        SEL selector = [invocation selector];
        if ([self.customer respondsToSelector:selector]) {
            
            [invocation setTarget:self.customer];
            [invocation invoke];
            
        } else {
        
            NSString *selectorString = NSStringFromSelector(invocation.selector);
            
            invocation.selector    = NSSelectorFromString(@"nullExcute:");
            AbstractExcute *excute = [AbstractExcute shareInstance];
            [invocation setTarget:excute];
            
            const char *className      = class_getName([self class]);
            NSArray    *classNameArray = nil;
            if (self.customer) {
                
                classNameArray = @[[NSString stringWithUTF8String:className], selectorString, @""];
                
            } else {
            
                classNameArray = @[[NSString stringWithUTF8String:className], selectorString];
            }
            
            [invocation setArgument:&classNameArray atIndex:2];
            [invocation invoke];
        }
    }
    
    @end
    //
    //  AbstractExcute.h
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface AbstractExcute : NSObject
    
    + (instancetype)shareInstance;
    
    @end
    //
    //  AbstractExcute.m
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import "AbstractExcute.h"
    
    @implementation AbstractExcute
    
    + (instancetype)shareInstance {
    
        static AbstractExcute *sharedAbstractExcute = nil;
        
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            sharedAbstractExcute = [[self alloc] init];
        });
        
        return sharedAbstractExcute;
    }
    
    - (void)nullExcute:(NSArray *)className {
    
        if (className.count == 3) {
            
            NSLog(@"%@ 设置了代理,但该代理没有实现 %@ 方法", className[0], className[1]);
            
        } else {
        
            NSLog(@"%@ 没有设置代理,方法 %@ 没有执行", className[0], className[1]);
        }
        
    }
    
    @end

    细节

    NSProxy子类实现的关键所在

  • 相关阅读:
    a++与++a区别
    powerdesigner 15.1 逆向工程 sqlserver2008 、sqlserver2005 带注释
    Docker部署vue+nginx项目
    Spring Cloud项目部署(四)上传docker镜像
    Spring Cloud项目部署(三)使用maven插件上传docker镜像的相关配置
    centos7 IP设置
    Spring Cloud项目部署(二)docker开启2375端口
    Spring Cloud项目部署(一)docker安装
    高并发网站架构设计(转)
    Element UI 那些坑
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4703259.html
Copyright © 2020-2023  润新知