iOS开发-对多个对象进行消息转发

文章目录

目的

参考NSProxy的实现,那么我们需要通过对多个消息的转发如何做呢?

  1. 如何存储对象,强引用集合对象已经不可取,会使得对象引用计数+1,所以可以采用OC中弱引用集合 NSPointerArray

参考以下文章:
http://www.isaced.com/post-235.html
https://www.jianshu.com/p/9d1c34999f3e

  1. 通过消息转发机制中的forwardingTargetForSelector方法,我们使用performSelector方法有一个问题是,当方法返回值不确定时,对其返回值的引用关系如何处理。返回值需要保存吗?

参考以下文章:
https://www.jianshu.com/p/4f5566125148

https://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown

对于第二个问题,由于各个类中的方法返回值可能不一,通过方法签名的返回类型来判断处理或许是一个好的选择,但是感觉并没有必要。

类似下面这种返回值类型判断:

	NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
    if(methodSig == nil) {
        return nil;
    }
    const char* retType = [methodSig methodReturnType];

    if (strcmp(retType, @encode(void)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        return nil;
    }

    if (strcmp(retType, @encode(NSInteger)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        NSInteger result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
	... more see @encode type in Object-C

还需要考虑线程执行问题,以及同一组方法返回值执行完后才能开始下一个方法,所以并不是很有必要。

实现

最终我这样实现的:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface HCProxy : NSObject

- (void)addObject:(id)object;

- (void)removeObjectAtIndex:(NSUInteger)index;

- (NSArray *)allObjects;

@end

NS_ASSUME_NONNULL_END
#import "HCProxy.h"

@interface HCProxy ()
@property (nonatomic, strong) NSPointerArray *weakArray;
@end

@implementation HCProxy

- (void)addObject:(id)object {
    [self.weakArray addPointer:(__bridge void *)object];
}

- (void)removeObjectAtIndex:(NSUInteger)index; {
    [self.weakArray removePointerAtIndex:index];
}

- (NSArray *)allObjects {
    return self.weakArray.allObjects;
}

- (NSPointerArray *)weakArray {
    if (!_weakArray) {
        _weakArray = [NSPointerArray weakObjectsPointerArray];
    }
    return _weakArray;
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    for (NSObject* obj in self.weakArray) {
        if (obj && ![obj isKindOfClass:[NSNull class]]) {
            if ([obj respondsToSelector:aSelector]) {
                #pragma clang diagnostic push
                #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [obj performSelector:aSelector withObject:nil];
                #pragma clang diagnostic pop
            }
        }
    }
    return nil;
}


- (void)forwardInvocation:(NSInvocation *)invocation {
    void *null = NULL;
    [invocation setReturnValue:&null];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}


@end

在ViewController中测试

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    HCProxy *proxy;
    //@autoreleasepool {
        Person *person = [Person new];
        dog *d = [dog new];
        
        proxy = [[HCProxy alloc] init];
        [proxy addObject:person];
        [proxy addObject:d];
    //}
    
    [proxy performSelector:@selector(call)];
    NSLog(@"----");
}

结果如下:

2020-04-19 00:33:32.540234+0800 HCProxy[1182:6015706] -[Person call]
2020-04-19 00:33:32.540443+0800 HCProxy[1182:6015706] -[dog call]
2020-04-19 00:33:32.540619+0800 HCProxy[1182:6015706] ----
2020-04-19 00:33:32.560592+0800 HCProxy[1182:6015706] -[dog dealloc]
2020-04-19 00:33:32.560761+0800 HCProxy[1182:6015706] -[Person dealloc]

链接:https://pan.baidu.com/s/1TVDn9EN1bHvSYOzW0vufSg
密码:yz3l


生活中有着太多无奈,但是某一天你跳出这个圈,你就发现,只需要你静下心来处理,生活会井井有条

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS开发中,支付是一个非常重要的功能。在开发支付时,需要考虑到支付流程、支付方式、支付安全等方面的内容。以下是一些开发支付的要点: 1. 集成支付SDK iOS开发中,一般使用第三方支付SDK来实现支付功能。常见的支付SDK包括:支付宝SDK、微信支付SDK、银联支付SDK等。在使用SDK前,需要先注册开发者账号,并获取相应的API Key和App ID等信息。 2. 支付流程 支付流程一般包括以下几个步骤: - 用户选择支付方式; - 向支付平台发起支付请求; - 用户输入支付密码; - 支付平台返回支付结果; - 应用根据支付结果进行相应的处理。 3. 支付安全 支付安全是非常重要的。在开发中,需要考虑到以下方面: - 用户信息的安全保护:包括用户的账号、密码、支付信息等; - 支付数据的安全保护:对于涉及到支付的数据,需要采用加密算法进行保护,避免被非法攻击者窃取; - 安全审计:需要对支付过程中的各个环节进行安全审计,及时发现并修复漏洞。 4. 支付方式 在iOS开发中,常见的支付方式包括: - 支付宝支付:支持PC端、移动端、扫码支付等多种支付方式; - 微信支付:支持微信内支付、H5支付、APP支付等多种支付方式; - 苹果支付:支持应用内购买,用户可以直接使用Apple ID进行支付。 需要根据应用的实际情况,选择适合的支付方式。 总之,开发支付需要考虑到多个方面的内容,包括支付流程、支付方式、支付安全等,需要仔细规划和实现,以保证支付功能的正常运作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值