18

有人可以提供一个使用 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 操作的简单示例。

4

2 回答 2

15

您无法观察数组的变化。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

于 2013-09-13T13:01:55.477 回答
2

克里斯解决方案的快速等价物:

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)
于 2014-11-19T08:51:48.263 回答