1

我想在我的班级 cSoundChannel 中观察 NSMutableArray。因此,在阅读了这篇文章 Observing an NSMutableArray for insert/removal之后 ,我以这种方式实现了关键观察。

对于 cSoundChanel 类,

我的可变数组属性是

 @property (assign, nonatomic) NSMutableArray* midiDevices;

我在类中使用 kvo 数组访问器介绍的函数如下:

- (void) addmidiDevicesObject:(NSObject *) str {
    [self insertObject:str inMidiDevicesAtIndex:[_midiDevices count]];
}

- (void)insertObject:(NSObject *)str inMidiDevicesAtIndex:(NSUInteger)index {
    [self.midiDevices insertObject:str atIndex:index];
    return;
}

对于需要观察 midiDevices 的 ViewController.m 文件,我执行了以下操作。

[self.cSoundChannel addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

并期望能够在...中观察可变数组

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"midiDevices"]) {
        NSLog(@"Let's see!");
    }
}

但唉......它没有打印“让我们看看!” 观察其他事情...... NSString 等工作......

有什么我错过的吗?帮助!

4

2 回答 2

2

您的代码在midiDevices. 您还需要实施removeObjectFromMidiDevicesAtIndex:

- (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices removeObjectAtIndex:index];
}

有关完整详细信息,请参阅键值编码编程指南。具体参见可变索引访问器。


编辑:以下示例代码演示了我所描述的内容,并打印“让我们看看!” 正如预期的那样。删除removeObjectFromMidiDevicesAtIndex:将重新引入在 OP 代码中看到的错误。

#import <Foundation/Foundation.h>

@interface Observed : NSObject
@property (nonatomic) NSMutableArray* midiDevices;
@end

@implementation Observed

- (id)init {
  self = [super init];
  if (self) {
    _midiDevices = [NSMutableArray new];
  }
  return self;
}

- (void) addmidiDevicesObject:(NSObject *) str {
  [self insertObject:str inMidiDevicesAtIndex:[_midiDevices count]];
}

- (void)insertObject:(NSObject *)str inMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices insertObject:str atIndex:index];
}

- (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices removeObjectAtIndex:index];
}

@end

@interface Observer : NSObject
@property (nonatomic) Observed *observed;
@end

@implementation Observer

- (id)init {
  self = [super init];
  if (self) {
    _observed = [Observed new];
    [_observed addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  }
  return self;
}

- (void)dealloc {
  [_observed removeObserver:self forKeyPath:@"midiDevices"];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  if ([keyPath isEqualToString:@"midiDevices"]) {
    NSLog(@"Let's see!");
  }
}

@end

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    Observer *observer = [Observer new];
    [observer.observed addmidiDevicesObject:@"test"];
  }
  return 0;
}
于 2013-09-13T11:19:08.507 回答
1

仅仅拥有一个NSMutableArray不会让你有能力观察变化。您需要使用NSKeyValueCoding协议“mutableArrayValueForKey”创建一个可变数组。这个数组是一个“特殊”数组,只要数组的内容发生变化,就会触发 KVO 消息。

这里需要两个数组。一个是我的“真实”数据,在您的情况下是 midiDevices,然后是第二个数组,以这种方式创建:

mutableMidiDevices = [self mutableArrayValueForKey:@"midiDevices"];

从这里,您只需将对象添加/删除到您的“mutableMidiDevices”,并且根本不访问原始的“midiDevices”(您需要定义的 KVO 例程(.

以下是您的 KVO 例程:

- (NSUInteger) countOfMidiDevices;
- (id) objectInMidiDevicesAtIndex:(NSUInteger)index;
- (void) replaceObjectInMidiDevicesAtIndex:(NSUInteger)index withObject:(id)object;
- (void) insertObject:(id)midiDevice inMidiDevicesAtIndex:(NSUInteger)index;
- (void) removeObjectFromMidiDevicesAtIndex:(NSUInteger)index;

我现在不确定你是否需要定义所有这些例程,但这就是我上次做 KVO 时所做的。这些例程中的每一个都应该修改原始的midiDevices 数组。

因此,这个想法是您从对象外部和内部添加/删除“mutableMidiDevices”。这将保证 KVO 消息触发。

在您的对象内部,您可以通过定义 KVO 例程来修改真正的“midiDevices”数组。

希望这可以帮助。

于 2013-09-13T14:47:30.700 回答