RAC框架源码解析之RAC集合类

2018-04-21  本文已影响12人  Jimi

1、RACTuple

RACTuple是一个元祖,也是一个集合,操作的方式和NSArray差不多,我们可以简单的看一下它的头文件,它有三个类方法、一个获取下标的实例方法以及获取所有元素的方法。

@interface RACTuple : NSObject <NSCoding, NSCopying, NSFastEnumeration>

@property (nonatomic, readonly) NSUInteger count;

/// These properties all return the object at that index or nil if the number of 
/// objects is less than the index.
@property (nonatomic, readonly, nullable) id first;
@property (nonatomic, readonly, nullable) id second;
@property (nonatomic, readonly, nullable) id third;
@property (nonatomic, readonly, nullable) id fourth;
@property (nonatomic, readonly, nullable) id fifth;
@property (nonatomic, readonly, nullable) id last;

/// Creates a new tuple out of the array. Does not convert nulls to nils.
+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array;

/// Creates a new tuple out of the array. If `convert` is YES, it also converts
/// every NSNull to RACTupleNil.
+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array convertNullsToNils:(BOOL)convert;

/// Creates a new tuple with the given objects. Use RACTupleNil to represent
/// nils.
+ (instancetype)tupleWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;

/// Returns the object at `index` or nil if the object is a RACTupleNil. Unlike
/// NSArray and friends, it's perfectly fine to ask for the object at an index
/// past the tuple's count - 1. It will simply return nil.
- (nullable id)objectAtIndex:(NSUInteger)index;

/// Returns an array of all the objects. RACTupleNils are converted to NSNulls.
- (NSArray *)allObjects;

/// Appends `obj` to the receiver.
///
/// obj - The object to add to the tuple. This argument may be nil.
///
/// Returns a new tuple.
- (__kindof RACTuple *)tupleByAddingObject:(nullable id)obj;

@end

2、RACSequence

RACSequence主要的目的是代替NSArray以及NSDictionary,它可以使用快速的遍历,最简单最常用的应用场景就是解析数据,例如字典转模型等。最主要的是遍历的数据返回的是一个信号,并已发送信号的方式返回给你,下面来一个简单的例子

    //原生OC数组
    NSArray *arr = @[@"111",@"222",@666];
    //转换为RAC集合
    RACSequence *requence = arr.rac_sequence;
    //遍历(返回值是信号)
    RACSignal *signal = requence.signal;
    //订阅信号
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

控制台打印结果

2018-04-21 15:35:06.695517+0800 RAC集合类[42729:1783382] 111
2018-04-21 15:35:06.695773+0800 RAC集合类[42729:1783382] 222
2018-04-21 15:35:06.696155+0800 RAC集合类[42729:1783382] 666

如果你们认为RAC只是简单遍历一下打印,那不是用系统的for循环或者forin就搞定了吗?RAC当然有其独到之处,前面我们说到RAC结合了响应式编程、函数式编程、链式编程。可以一行代码搞定

    //原生OC数组
    NSArray *arr = @[@"111",@"222",@666];
    //遍历
    [arr.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    }];

控制器打印结果

2018-04-21 15:43:14.314912+0800 RAC集合类[42918:1796266] 111
2018-04-21 15:43:14.315271+0800 RAC集合类[42918:1796266] 222
2018-04-21 15:43:14.316806+0800 RAC集合类[42918:1796266] 666

字典如何遍历?和字典遍历稍微不一样的就是x返回的是一个元祖,这里涉及到一个宏 RACTupleUnpack 专门用来解析元祖的,关于这宏的解释我也是直接放弃翻译,有大牛解析出来的麻烦通知我,哈哈

    //声明字典
    NSDictionary *dict = @{
                           @"name":@"JM",
                           @"age":@"18"
                           };
    
    //字典转集合
    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
        NSLog(@"%@",x);
        
        //RACTupleUnpack宏用来解析元祖
        RACTupleUnpack(NSString *key, NSString *value) = x;
        NSLog(@"key---%@, value---%@",key, value);
    }];

控制台打印结果

2018-04-21 15:55:23.153807+0800 RAC集合类[43286:1816660] <RACTwoTuple: 0x60000001fc80> (
    name,
    JM
)
2018-04-21 15:55:23.154372+0800 RAC集合类[43286:1816660] key---name, value---JM
2018-04-21 15:55:23.155242+0800 RAC集合类[43286:1816660] <RACTwoTuple: 0x604000209a80> (
    age,
    18
)
2018-04-21 15:55:23.155407+0800 RAC集合类[43286:1816660] key---age, value---18

RACTupleUnpack宏源码

#define RACTupleUnpack_(...) \
    metamacro_foreach(RACTupleUnpack_decl,, __VA_ARGS__) \
    \
    int RACTupleUnpack_state = 0; \
    \
    RACTupleUnpack_after: \
        ; \
        metamacro_foreach(RACTupleUnpack_assign,, __VA_ARGS__) \
        if (RACTupleUnpack_state != 0) RACTupleUnpack_state = 2; \
        \
        while (RACTupleUnpack_state != 2) \
            if (RACTupleUnpack_state == 1) { \
                goto RACTupleUnpack_after; \
            } else \
                for (; RACTupleUnpack_state != 1; RACTupleUnpack_state = 1) \
                    [RACTupleUnpackingTrampoline trampoline][ @[ metamacro_foreach(RACTupleUnpack_value,, __VA_ARGS__) ] ]

联系我:
qq: 1245424073
微信: liujunmin6980

上一篇下一篇

猜你喜欢

热点阅读