Пример ReactiveCocoa с NSMutableArray push/pop?
Может ли кто-нибудь предоставить однострочный пример использования абстракций ReactiveCocoa для достижения чего-то вроде этого:
// pseudo-code
NSMutableArray *array = @[[] mutableCopy];
RACSignal *newValue = RACAbleWithStart(array); // get whole array or maybe just added/removed element on push/pop
[newValue subscribeNext:^(NSArray *x) {
// x is whole array
}]
[newValue subscribeNext:^(id x) {
// x is new value
}]
[newValue subscribeNext:^(id x) {
// x is removed value
}]
Я вижу, что некоторые расширения для NSArray были удалены в пользу Mantle https://github.com/ReactiveCocoa/ReactiveCocoa/pull/130 Но все еще не могу найти простой пример манипуляции NSArray.
2 ответа
Вы не можете наблюдать массив для изменений. ReactiveCocoa использует наблюдение значения ключа. Который, как следует из названия, наблюдает только изменения ключевых атрибутов (членов словаря, свойств и т. Д.).
Что вы можете сделать, это наблюдать свойство массива для изменений:
@interface Blah : NSObject
@property (copy, readonly) NSArray *arrayProperty;
@end
// later...
Blah *blah = [Blah new];
[RACObserve(blah, arrayProperty) subscribeNext:^(NSArray *wholeArray){}];
Если вы хотите знать, какие объекты были вставлены / удалены, у вас есть два варианта. Вы можете решить это, сохранив каждый массив и сравнив каждый с предыдущим. Это самое простое, но плохо работает с очень большими массивами. AFAIK, ReactiveCocoa не имеет встроенных операций для этого.
Или вы можете реализовать средства доступа к коллекции KVO и убедиться, что изменения в массиве сделаны с использованием mutableArrayValueForKey:
, Это позволяет избежать создания нового массива всякий раз, когда вносятся какие-либо изменения, а также уведомляет наблюдателей об изменениях, внесенных в прокси-массив, возвращаемый mutableArrayValueForKey:
,
Наблюдение за информацией об изменениях с помощью ReactiveCocoa несколько сложнее:
RACSignal *changeSignal = [blah rac_valuesAndChangesForKeyPath:@keypath(blah, arrayProperty) options: NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld observer:nil];
[changeSignal subscribeNext:^(RACTuple *x){
NSArray *wholeArray = x.first;
NSDictionary *changeDictionary = x.second;
}];
Словарь изменений сообщает вам, какие изменения были внесены в массив, какие объекты были вставлены / удалены, а также индексы вставленных / удаленных объектов.
Он задокументирован по адресу: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html
Быстрый эквивалент для решения Криса:
let signal = self.object.rac_valuesAndChangesForKeyPath("property", options: NSKeyValueObservingOptions.New | NSKeyValueObservingOptions.Old, observer:self.object)
signal.subscribeNext { (object) -> Void in
if let tuple = object as? RACTuple {
var wholeArray = tuple.first as? NSArray
var changeDictionary = tuple.second as? NSDictionary
}
}
Также убедитесь, что вы изменили свойство содержимого в соответствии с требованиями KVO.
// This is wrong and wont send values to RAC signals
[self.contents addObject:object];
// This is correct and will send values to RAC signals
NSMutableArray *contents = [account mutableArrayValueForKey:@keypath(self, contents)];
[contents addObject:object];
Изменить: чтобы сделать вещи более понятными, поместите имя вашего массива вместо свойства. Например:
lazy var widgets:NSMutableArray = NSMutableArray()
let signal = self.rac_valuesAndChangesForKeyPath("widgets", options: NSKeyValueObservingOptions.New | NSKeyValueObservingOptions.Old, observer:self)