观察NSMutableArray,使用了数组访问器,但仍然没有运气

时间:2013-09-13 10:12:37

标签: ios objective-c arrays nsmutablearray

我想在我的班级cSoundChannel中观察一个NSMutableArray。因此阅读这篇文章后 Observing an NSMutableArray for insertion/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等工作......

我错过了什么吗?救命!

2 个答案:

答案 0 :(得分:2)

您的代码在midiDevices上不完全符合KVC标准。您还需要实施removeObjectFromMidiDevicesAtIndex:

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

有关详细信息,请参阅Key-Value Coding Programming Guide。具体请参见Mutable Indexed Accessors。


编辑:以下示例代码演示了我所描述的内容,并打印了#34;让我们看看!"正如所料。删除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;
}

答案 1 :(得分: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”&amp;在你的对象里面。这将保证KVO消息的触发。

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

希望这有帮助。