Ios 观察NSMutableArray时,使用了数组访问器,但仍然不走运
我想观察类cSoundChannel中的NSMutableArray。所以看完这篇文章 我以这种方式实现了关键点 对于cSoundChanel类 可变数组的属性是Ios 观察NSMutableArray时,使用了数组访问器,但仍然不走运,ios,objective-c,arrays,nsmutablearray,Ios,Objective C,Arrays,Nsmutablearray,我想观察类cSoundChannel中的NSMutableArray。所以看完这篇文章 我以这种方式实现了关键点 对于cSoundChanel类 可变数组的属性是 @property (assign, nonatomic) NSMutableArray* midiDevices; [self.cSoundChannel addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKey
@property (assign, nonatomic) NSMutableArray* midiDevices;
[self.cSoundChannel addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
我在类中使用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;
}
对于需要观察MIDI设备的ViewController.m文件,我执行了以下操作。
@property (assign, nonatomic) NSMutableArray* midiDevices;
[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!");
}
}
但是,唉。。。它没有打印“让我们看看!”
观察其他事情。。。字符串等工作
有什么我遗漏的吗?救命啊 您的代码在
MIDI设备上不完全兼容KVC。您还需要实现removeObjectfromMidiDeviceStatIndex:
:
- (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index {
[self.midiDevices removeObjectAtIndex:index];
}
有关详细信息,请参阅。具体请参见可变索引访问器
编辑:下面的示例代码演示了我所描述的内容,并按预期打印“让我们看看!”。从MidiDeviceStatIndex中删除RemoveObjects:
将重新引入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;
}
#导入
@观察到的接口:NSObject
@属性(非原子)NSMutableArray*MIDI设备;
@结束
@观察到的执行情况
-(id)init{
self=[super init];
如果(自我){
_midiDevices=[NSMutableArray new];
}
回归自我;
}
-(void)addmidiDevicesObject:(NSObject*)str{
[自插入对象:str inMidiDeviceStatIndex:[u midiDevices count];
}
-(void)insertObject:(NSObject*)str inMidiDeviceStatIndex:(nsInteger)索引{
[self.midirects insertObject:str atIndex:index];
}
-(void)RemoveObjectfromMidiDeviceStatIndex:(nsInteger)索引{
[self.midiDevices removeObjectAtIndex:index];
}
@结束
@接口观察者:NSObject
@观察到的性质(非原子)*观察到的;
@结束
@执行观察员
-(id)init{
self=[super init];
如果(自我){
_观察=[观察到的新];
[|观察者:自分叉路径:@“MIDI设备”选项:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld上下文:nil];
}
回归自我;
}
-(无效)解除锁定{
[_-observeremoveObserver:self-forKeyPath:@“midiDevices”];
}
-(void)observeValueForKeyPath:(NSString*)对象的键路径:(id)对象更改:(NSDictionary*)更改上下文:(void*)上下文{
if([keyPath IsequalString:@“MIDI设备”]){
NSLog(@“让我们看看!”);
}
}
@结束
int main(int argc,const char*argv[]{
@自动释放池{
观察员*观察员=[新观察员];
[observer.observed addmidiDevicesObject:@“test”];
}
返回0;
}
仅仅拥有一个NSMutableArray
并不能让您监视更改。您需要使用NSKeyValueCoding
协议-“mutableArrayValueForKey”创建一个可变数组。此阵列是一个“特殊”阵列,每当阵列内容发生更改时,它都会发出KVO消息
这里需要两个数组。一个是我的“真实”数据,在您的例子中是MIDI设备,然后是第二个数组,通过以下方式创建:
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例程来修改真正的“MIDI设备”数组
希望这能有所帮助。您在哪个类中拥有代码的每个部分?最重要的是-(void)observeValueForKeyPath:在addObserver:self.Hi中作为观察者发送的同一个类中,我编辑以包含该类,谢谢…这不是问题所在,也不是答案。将其更改为注释,可能是他的代码作为提示。这是问题所在,通过使其符合KVC,将调用观察者。太好了。我只需要添加-(void)removeObjectFromMidiDevicesAtIndex:(nsInteger)索引,如您所说。谢谢!我这里有一个新问题。如果观察到的类中mididevices nsmutablearray中有多个项,我在执行nsmutablearray*midiDevicesArray=[change objectForKey:NSKeyValueChangeNewKey]时只看到一个对象;这是为什么?我意识到,出于某种原因,观测值仅显示NSMutableArray中的变化,对于添加到被观测数组中的2项,它被称为2次。