zoukankan      html  css  js  c++  java
  • 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子类实现的关键所在

  • 相关阅读:
    Java 老兵不死,Kotlin 蓄势待发
    程序员写代码时戴着耳机,在听什么?
    推荐 7 个提升前端编程效率的 VSCode 插件
    去掉烦人的 !=null
    透析!软件开发未来 10 年的 8 个趋势
    10月01日总结
    09月29日总结
    09月28日总结
    09月27日总结
    09月26日总结
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4703259.html
Copyright © 2011-2022 走看看