ReactiveCocoa,有一种更好的RAC方式,可以先刷新

时间:2014-08-26 18:12:53

标签: ios objective-c reactive-cocoa

这是情况

  

我有一个ViewModel(好的,遵循MVVM架构),它有一个名为“specialtySegments”的数组属性,以及一个名为“generic”的标志属性,我想在更改泛型值时更新specialSegments值再次

代码段

- (instancetype)initWithTerritory:(SAPTerritory *)territory {
    self = [super init];
    if (self) {
        _territory = territory;
        _generic = NO;            
        _selectedProduct = [_products firstObject];

        RAC(self, specialtySegments) = [self querySpecialtySegments];

    }

    return self;
}

- (RACSignal *)querySpecialtySegments {
    return [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [self asynQuerySpecialtySegments:^(NSArray *model) {
            [subscriber sendNext:model];
            [subscriber sendCompleted];
        }];


        return [RACDisposable disposableWithBlock:^{

        }];
    }] deliverOn:[RACScheduler mainThreadScheduler]] publish] autoconnect];
}


- (void)refreshData {
    [self asynQuerySpecialtySegments:^(NSArray *model) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.specialtySegments = model;
        });
    }];                    
}

在ViewController中

@weakify(self);
[[RACObserve(self.viewModel, specialtySegments) filter:^BOOL(id value) {
    return (value != nil);
}] subscribeNext:^(id x) {
    @strongify(self) {
        [self.indicatorView stopAnimating];
        self.indicatorView.hidden = YES;
        [self.tableView reloadData];
    }
}];

还有一些地方可以改变通用值,比如

if (specialtyButton.selected == NO) {
    self.viewModel.generic = NO;
    genericButton.selected = NO;
    specialtyButton.selected = YES;
    [self.viewModel refreshData];
}

这就是我现在所知道的,我认为这不是一种幻想。

我可以在ViewModel中观察泛型属性,再看看subscripNext和第一个信号。

我试过这样,但是代码没有输入 querySpecialtySegments ,我在方法中加了一个断点。

[RACObserve(self, generic) subscribeNext:^(id x) {
    [self querySpecialtySegments];
}];

如果我喜欢这个,那么 asynQuerySpecialtySegments 方法会输入两次,就像之前的RAC一样,它会运行一次,我想

    [RACObserve(self, generic) subscribeNext:^(id x) {
        [self asynQuerySpecialtySegments:^(NSArray *model) {
            dispatch_async(dispatch_get_main_queue(), ^{
                self.specialtySegments = model;
            });
        }];
    }];

我是ReactiveCocoa的新手,尝试在项目中使用,所以有更好的方法来解释我上面描述的事情,谢谢你

2 个答案:

答案 0 :(得分:0)

一切正确,它在启动时不起作用,因为你是用下划线设置实例变量,如果你在init方法中会调用self.generic = NO; ,RACObserve将按计划运作。 发生这种情况,因为当您设置实例变量时,将不会调用setter,并且也不会调用KVO的方法 - willChangeValue:和-didChangeValue :.

答案 1 :(得分:0)

好的,经过一天的阅读,我觉得我自己找到了答案

关键点是

  

大多数信号开始&#34;冷,&#34;这意味着他们在订阅之前不会做任何工作。

所以这部分代码应该像这样改变

[RACObserve(self, generic) subscribeNext:^(id x) {
    [[self querySpecialtySegments] subscribeNext:^(id x) { // subscription is the key to trigger
        self.specialtySegments = x;  // would trigger the observer in view controller to do something
    }];
}];

<强>更新 个人的想法是在ViewModel中观察泛型属性,然后触发View更新某些东西不是最佳选择,某种黑魔法,不调用刷新或其他东西,但视图自动刷新。使用公共方法 -reloadData 是一个不错的选择

- (void)refreshData {

    @weakify(self);
    [[self querySpecialtySegments] subscribeNext:^(id x) {
        @strongify(self) {
            self.specialtySegments = x;
        }
    }];
}