ReactiveCocoa入门实践

今天由于项目没有那么繁忙,于是就研究了一下ReactiveCocoa.简单介绍一下,ReactiveCocoa是响应式编程在iOS中的一个实现框架,它的开源地址是:ReactiveCocoa,在网络上也看到很多关于它的文章,但是还是不太懂,于是就参照其他的文章自己实现了一下.

首先来说一下merge,

//Sends the latest `next` from any of the signals.

//Returns a signal that passes through values from each of the given signals,

//and sends `completed` when all of them complete. If any signal sends an error

//the returned signal sends `error` immediately.

//+ (RACSignal *)merge:(id)signals;

这是源码

+ (RACSignal *)merge:(id)signals {
    NSMutableArray *copiedSignals = [[NSMutableArray alloc] init];
    for (RACSignal *signal in signals) {
        [copiedSignals addObject:signal];
    }

    return [[[RACSignal
        createSignal:^ RACDisposable * (id subscriber) {
            for (RACSignal *signal in copiedSignals) {
                [subscriber sendNext:signal];
            }

            [subscriber sendCompleted];
            return nil;
        }]
        flatten]
        setNameWithFormat:@"+merge: %@", copiedSignals];
}



这些文字的说明是:

合并中的任何一个signal触发,都会传送到合并后的signal;

当合并的一组signal都发送了完成后,当前signal的发送complete的消息。

再者是combineLatest,

- (RACSignal *)combineLatestWith:(RACSignal *)signal {
    NSCParameterAssert(signal != nil);

    return [[RACSignal createSignal:^(id subscriber) {
        RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];

        __block id lastSelfValue = nil;
        __block BOOL selfCompleted = NO;

        __block id lastOtherValue = nil;
        __block BOOL otherCompleted = NO;

        void (^sendNext)(void) = ^{
            @synchronized (disposable) {
                if (lastSelfValue == nil || lastOtherValue == nil) return;
                [subscriber sendNext:RACTuplePack(lastSelfValue, lastOtherValue)];
            }
        };

        RACDisposable *selfDisposable = [self subscribeNext:^(id x) {
            @synchronized (disposable) {
                lastSelfValue = x ?: RACTupleNil.tupleNil;
                sendNext();
            }
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            @synchronized (disposable) {
                selfCompleted = YES;
                if (otherCompleted) [subscriber sendCompleted];
            }
        }];

        [disposable addDisposable:selfDisposable];

        RACDisposable *otherDisposable = [signal subscribeNext:^(id x) {
            @synchronized (disposable) {
                lastOtherValue = x ?: RACTupleNil.tupleNil;
                sendNext();
            }
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            @synchronized (disposable) {
                otherCompleted = YES;
                if (selfCompleted) [subscriber sendCompleted];
            }
        }];

        [disposable addDisposable:otherDisposable];

        return disposable;
    }] setNameWithFormat:@"[%@] -combineLatestWith: %@", self.name, signal];
}

+ (RACSignal *)combineLatest:(id)signals {
    return [[self join:signals block:^(RACSignal *left, RACSignal *right) {
        return [left combineLatestWith:right];
    }] setNameWithFormat:@"+combineLatest: %@", signals];
}

上面是combineLatest的源码,其实它和数学中的逻辑与(&&)的意思是一样的,只有两个信号同事发送了sendNext事件,才会触发;

然而,merge和数学中的逻辑或(||)的意思是一样的,只要其中的一个信号发送了sendNext事件,就会触发。

我的demo就是运用ReactiveCocoa,通过三个UISlider控件的不断变化,来改变底部view的背景颜色。

主要代码如下:

 RACSignal *redSignal =   [self blindSlider:redSlider textField:redTextFiled];
  RACSignal *greenSignal =  [self blindSlider:greenSlider textField:greenTextField];
   RACSignal *blueSignal = [self blindSlider:blueSlider textField:blueTextField];
    [[[RACSignal combineLatest:@[redSignal,greenSignal,blueSignal]] map:^id(id value) {
        return [UIColor colorWithRed:[value[0] floatValue] green:[value[1] floatValue] blue:[value[2] floatValue] alpha:1];
    }] subscribeNext:^(id x) {
        showView.backgroundColor = x;
    }];

- (RACSignal *)blindSlider:(UISlider *)slider textField:(UITextField *)textField
{
    RACSignal *textSignal = [[textField rac_textSignal] take:1];
    RACChannelTerminal *signalSlider = [slider rac_newValueChannelWithNilValue:nil];
    RACChannelTerminal *signalText = [textField rac_newTextChannel];
    [signalText subscribe:signalSlider];
    [[signalSlider map:^id(id value) {
        return [NSString stringWithFormat:@"%.02f",[value floatValue]];
    }] subscribe:signalText];
    return [[signalText merge:signalSlider] merge:textSignal];
}

效果图如下:


ReactiveCocoa入门实践_第1张图片
颜色选择器

你可能感兴趣的:(ReactiveCocoa入门实践)