我想在我的班级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等工作......
我错过了什么吗?救命!
答案 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”数组。
希望这有帮助。