Използвайки combineLatest, има ли начин да разберете кой сигнал е излъчил събитието?

Както се посочва в заглавието, има начин да изпълните следното:

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

Така че в блока subscribeNext в момента не знам кой сигнал е изстрелян.

Проблемът, който се опитвам да разреша, е такъв, който включва генериране на сигнали за селектори (с помощта на rac_signalForSelector) и искам да бъда уведомен, когато някой от тези методи бъде уволнен. Искам да обединя събитията заедно, но не искам най-новата стойност за нито едно от тях, освен за метода, който всъщност е извикан.

e.g.

RACSignal *signal1 = [self rac_signalForSelector@selector(method1:)];
RACSignal *signal2 = [self rac_signalForSelector@selector(method2:)];

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

person Patrick    schedule 05.01.2016    source източник
comment
Не използвам combineLatest. Тук обаче усещам силно xyproblem.info настроение. Кой е по-големият проблем, който се опитвате да разрешите?   -  person Ian Henry    schedule 05.01.2016
comment
Редактирано, за да включи по-голямата картина, благодаря.   -  person Patrick    schedule 06.01.2016


Отговори (2)


Ако приемем, че signal1 и signal2 във вашия пример изпращат един и същи тип стойности и искате да направите едно и също нещо със стойностите от всеки сигнал, можете да използвате merge: вместо combineLatest:, за да получите просто сигнал за стойностите, които всяка задейства:

[[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSObject *latestValue) {
    NSLog(@"%@", latestValue);
}];

Ако искате да ги третирате по различен начин, тогава изобщо не е необходимо да използвате combineLatest: или merge: -- можете просто да се абонирате за всеки един поотделно.

Обърнете внимание, че една разлика между merge: и combineLatest: е, че с merge: вашият блок ще бъде извикан веднага щом бъде извикан първият метод -- той няма да чака, докато всеки метод бъде извикан поне веднъж, преди да започне да се задейства, както би combineLatest: . Ако това поведение е желателно, то може да се постигне с оператора then:.


В случай, че правите трябва да знаете не само аргумента на „най-скоро извикания“ метод, но също аргументите от последния път, когато другите методи са били извикани, и трябва да изчакате, докато всеки метод бъде извикан поне веднъж... едно нещо, което можете да направите, е да картографирате всеки сигнал в кортеж от (id whateverTheyActuallySent, NSUInteger sharedMonotonicallyIncreasingIdentifier), след това да комбинирате тези сигнали, след което да ги сортирате въз основа на това идентификатор.

Би било... неелегантно, но само много странна ситуация би оправдала това и ако смятате, че това е най-добрият подход, може да е добре да намалите още едно ниво, за да видите дали нещо друго може да бъде променено, така че да не не трябва да правя това в крайна сметка.

person Ian Henry    schedule 06.01.2016
comment
Благодаря за страхотния отговор, Иън, сливането определено беше това, което търсех. Мислех за вашето решение да използвате кортеж, но съм съгласен, че би било неелегантно. Чрез допълнително картографиране на signal1 и signal2 успях чисто и след това да използвам merge. наздраве - person Patrick; 06.01.2016

Както Иън спомена в отговора си, вероятно искате да използвате merge вместо combineLatest.

Тъй като не ви интересуват стойностите от rac_signalForSelector, можете да използвате оператор mapReplace, за да разграничите method1 и method2:

  RACSignal *signal1 = [[self rac_signalForSelector:@selector(method1:)] mapReplace:@YES];
  RACSignal *signal2 = [[self rac_signalForSelector:@selector(method2:)] mapReplace:@NO];

  [[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSNumber *latestValue) {
    if(latestValue.boolValue) {
      //first method was called
    }
  }];

Намерих този подход за полезен за обработка на "противоположни" събития, като rac_signalForControlEvents с параметри UIControlEventTouchDownInside и UIControlEventTouchUpInside.

person Michał Ciuba    schedule 06.01.2016